JAVA - 类 class (2)

183 阅读11分钟

继续上一个笔记 java - 类(1)

封装的概念

  • 通常情况下可以在测试类给成员变量赋值一些合法但不合理的数值,无论是编译阶段还是运行阶段都不会报错或者给出提示,此时与现实生活不符。

  • 为了避免上述错误的发生,就需要对成员变量进行密封包装处理,来隐藏成员变量的细节以及保证成员变量数值的合理性,该机制就叫做封装。

封装的实现流程

  • 私有化成员变量,使用private关键字修饰。

  • 提供公有的get和set方法,并在方法体中进行合理值的判断。

  • 在构造方法中调用set方法进行合理值的判断。

/*
    编程实现Student类的封装  封装类
 */
public class Student {
	
	// 1.私有化成员变量,使用private关键字修饰
	// private关键字修饰表示私有的含义,也就是该成员变量只能在当前类的内部使用
	private int id;       // 用于描述学号的成员变量
	private String name;  // 用于描述姓名的成员变量 
	
	// 3.在公有的构造方法中调用set方法进行合理值的判断
	public Student() {}
	public Student(int id, String name) {
		//this.id = id;
		//this.name = name;
		setId(id);
		setName(name);
	}
	
	// 2.提供公有的get和set方法,并在方法体中进行合理值的判断
	// 使用public关键字修饰表示公有的含义,也就是该方法可以在任意位置使用
	public int getId() {
		return id;
	}
	public void setId(int id) {
		if(id > 0) {
			this.id = id;
		} else {
			System.out.println("学号不合理!!!");
		}
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	// 自定义成员方法实现特征的打印
	// 什么修饰符都没有叫做默认的访问权限,级别介于private和public之间
	public void show() {
		//System.out.println("我是" + name + ",我的学号是" + id);
		System.out.println("我是" + getName() + ",我的学号是" + getId());
	}
}

static关键字

基本概念

  • 使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关。

  • static关键字修饰的成员可以使用引用.的方式访问,但推荐类名.的方式。

使用方式

  • 在非静态成员方法中既能访问非静态的成员又能访问静态的成员。 (成员:成员变量 + 成员方法, 静态成员被所有对象共享)

  • 在静态成员方法中只能访问静态成员不能访问非静态成员。 (成员:成员变量 + 成员方法, 因为此时可能还没有创建对象)

  • 在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰。 (不能滥用static关键字)

构造块和静态代码块

  • 构造块:在类体中直接使用{}括起来的代码块。

  • 每创建一个对象都会执行一次构造块。

  • 静态代码块:使用static关键字修饰的构造块。

  • 静态代码块随着类加载时执行一次

展示顺序


/*
    SuperTest类
*/
public class SuperTest {

    {
        System.out.println("SuperTest类中的构造块!"); // (2)      c
    }

    static {
        System.out.println("SuperTest类中的静态代码块!"); // (1)    a
    }

    public SuperTest() {
        System.out.println("SuperTest类中的构造方法体!"); // (3)    d
    }

    public static void main(String[] args) {

        // 使用无参方式构造对象
        SuperTest st = new SuperTest();
    }
}

/*
    SubSuperTest类 继承 SuperTest类
*/
public class SubSuperTest extends SuperTest {

    {
        System.out.println("==========SubSuperTest类中的构造块!"); // (2)      e
    }

    static {
        System.out.println("==========SubSuperTest类中的静态代码块!"); // (1)   b
    }

    public SubSuperTest() {
        //System.out.println("==========SubSuperTest类中的构造方法体!"); // (3)  f
        out.println("==========SubSuperTest类中的构造方法体!");
    }

    public static void main(String[] args) {

        // 使用无参方式构造子类的对象
        SubSuperTest sst = new SubSuperTest();
    }
}

单例设计模式的概念

  • 在某些特殊场合中,一个类对外提供且只提供一个对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式。

单例设计模式的实现流程

  • 私有化构造方法,使用private关键字修饰。

  • 声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰。

  • 提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰。

单例设计模式的实现方式

  • 单例设计模式的实现方式有两种:饿汉式 和 懒汉式,在以后的开发中推荐饿汉式。
// 声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
private static Singleton sin = new Singleton();  // 饿汉式
private static Singleton sin = null;               // 懒汉式

案例

  • 编程实现Singleton类的封装。

  • 编程实现SingletonTest类对Singleton类进行测试,要求main方法中能得到且只能得到该类的一个对象。


/*
    编程实现Singleton类的封装
 */
public class Singleton {
	
	// 2.声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
	//private static Singleton sin = new Singleton();  // 饿汉式
	private static Singleton sin = null;               // 懒汉式
	
	// 1.私有化构造方法,使用private关键字修饰
	private Singleton() {}
	
	// 3.提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
	public static Singleton getInstance() {
		//return sin;
		if(null == sin) {
			sin = new Singleton();
		}
		return sin;
	}
}


/*
    编程实现Singleton类的测试
 */
public class SingletonTest {
	
	public static void main(String[] args) {
		
		// 1.声明Singleton类型的引用指向该类型的对象
		//Singleton s1 = new Singleton();
		//Singleton s2 = new Singleton();
		//System.out.println(s1 == s2); // 比较变量s1的数值是否与变量s2的数值相等  false
		//Singleton.sin = null;  可以使得引用变量无效
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2); // true
	}
}

继承

继承的由来

image.png

继承的概念

  • 当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承。
  • 在Java语言中使用extends(扩展)关键字来表示继承关系。

  • 如:
    public class Worker extends Person{} - 表示Worker类继承自Person类 其中Person类叫做超类、父类、基类。
    其中Worker类叫做派生类、子类、孩子类。

    使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件。

继承的特点

  • 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问。

  • 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码 super() 的效果。

  • 使用继承必须满足逻辑关系:子类 is a 父类,也就是不能滥用继承。

  • Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类。

方法重写

方法重写的概念

  • 从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做方法的重写(Override)。

方法重写的原则

  • 要求方法名相同、参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型。
  • 要求方法的访问权限不能变小,可以相同或者变大。
  • 要求方法不能抛出更大的异常(异常机制)。

访问控制

####常用的访问控制符

修饰符本类本包子类外部包
public可以访问可以访问可以访问可以访问
protected可以访问可以访问可以访问不能访问
默认可以访问可以访问不能访问不能访问
private可以访问不能访问不能访问不能访问

注意事项

  • public修饰的成员可以在任意位置使用。

  • private修饰的成员只能在本类内部使用。

  • 通常情况下,成员方法都使用public关键字修饰,成员变量都使用private关键字修饰。

package语句的由来

  • 定义类时需要指定类的名称,但如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突的问题。这会给组件复用以及团队间的合作造成很大的麻烦!

  • 在Java语言中,用包(package)的概念来解决命名冲突的问题。

包的定义

  • 在定义一个类时,除了定义类的名称一般还要指定一个包名,格式如下:
    package 包名;
    package 包名1.包名2.包名3...包名n;

  • 为了实现项目管理、解决命名冲突以及权限控制的效果。

包的导入

  • 使用import关键字导入包。

  • 使用import关键字导入静态成员,从Java5.0开始支持。

final关键字

基本概念

  • final本意为"最终的、不可改变的",可以修饰类、成员方法以及成员变量。

使用方式

  • final关键字修饰类体现在该类不能被继承。
    • 主要用于防止滥用继承,如:java.lang.String类等。
  • final关键字修饰成员方法体现在该方法不能被重写但可以被继承。
    • 主要用于防止不经意间造成重写,如:java.text.Dateformat类中format方法等。
  • final关键字修饰成员变量体现在该变量必须初始化且不能改变。
    • 主要用于防止不经意间造成改变,如:java.lang.Thread类中MAX_PRIORITY等。

常量的概念

  • 在以后的开发中很少单独使用final关键字来修饰成员变量,通常使用public static final关键字共同修饰成员变量来表达常量的含义,常量的命名规范要求是所有字母都要大写,不同的单词之间采用下划线连。

  • public static final double PI = 3.14;

面试题

1. 关于封装的说法正确的是  [多选题]

A、拥有特征的类必须封装,否则编译无法通过。

B、封装就是私有化成员变量,提供公有的方法进行访问。

C、特征的访问就是通过 get 和 set 开头的方法。

D、其中 set 开头的方法用于取值,get 开头的方法用于赋值。

正确答案是:BC

2. 编写类成员时若不指定 publi、 protecte、 private 关键字时,则下面哪种位置能访问该成员  [多选题]

A、本类内部

B、本包内部

C、子类内部

D、其它包中的其它类内部

正确答案是:AB

具体解析如下:

  • 若不是指定明确的修饰符则表示为默认的访问权限,默认权限只能在本类和同一个包中的类访问。

3. 关于 final 关键字描述错误的是  [多选题]

A、final 关键字修饰类表示可以被继承

B、final 关键字修饰方法表示不能被继承

C、final 关键字修饰成员变量不能初始化

D、final 关键字修饰成员变量可以被赋值

正确答案是:ABCD

具体解析如下:

  • final 关键字修饰类体现在该类不能被继承。

  • final 关键字修饰成员方法体现在该方法不能被重写但可以被继承。

  • final 关键字修饰成员变量体现在该变量必须初始化且不能改变。

4. static 关键字的使用方式说法正确的是  [多选题]

A、非静态方法中只能访问非静态成员

B、非静态方法中既能访问非静态方法又能访问静态方法

C、静态方法中只能直接访问静态成员

D、静态方法中既能访问静态成员又能访问非静态成员

正确答案是:BC

具体解析如下:

  • 在非静态成员方法中既能访问非静态的成员又能访问静态的成员。

  • 在静态成员方法中只能访问静态成员不能访问非静态成员。

5. 关于构造块和静态代码块的说法正确的是  [多选题]

A、构造块就是在方法体中使用一对花括号括起来的代码块。

B、构造块是在构造方法调用结束后执行的。

C、静态代码块会随着类的加载而准备就绪并执行。

D、每创建一个对象就会执行一次构造块。

正确答案是:CD

具体解析如下:

  • 构造块:在类体中直接使用{}括起来的代码块。

  • 构造块会在构造方法体执行前执行。

B C D A 选项 回答错误, 正确答案为 C 答案解析 解析:正确答案是:C,具体解析如下:

6. 若类 A 继承了类 B,类 B 继承了类 C,则下列描述正确的是  [多选题]

A、类 A 只会继承类 B 中的成员。

B、类 A 只会继承类 C 中的成员

C、类 A 同时继承了类 B 和类 C 中的成员。

D、类 A 不会继承类 B 和类 C 中的成员。

正确答案是:C

具体解析如下:

  • 类 B 继承了类 C 后相当于有了类 C 的成员,类 A 再继承类 B,相当于把类 B 和类 C 的成员都继承了下来。