封装性
信息的封装和隐藏
class Animal {
private int legs;// 将属性legs定义为private,只能被Animal类内部访问
public void setLegs(int i) { // 在这里定义方法 eat() 和 move()
if (i != 0 && i != 2 && i != 4) {
System.out.println("Wrong number of legs!");
return;
}
legs = i;
}
public int getLegs() {
return legs;
}
}
public class Zoo {
public static void main(String args[]) {
Animal xb = new Animal();
xb.setLegs(4); // xb.setLegs(-1000);
//xb.legs = -1000; // 非法
System.out.println(xb.getLegs());
}
}
权限修饰符
继承性
- 个人感觉继承的关键字extends挺形象的,翻译成“扩展”,这样就不会迷谁继承谁,谁是子集谁是父集。
- IntelliJIDEA 查看子父类关系快捷键:
ctrl+H
。
子类对象的实例化全过程
- 从结果上来看:(继承性)
- 子类继承父类以后,就获取了父类中声明的属性或方法。
- 创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。
- 从过程上来看:
- 当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,…直到调用java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用。
明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
多态性
个人理解:有的时候你不清楚具体要用什么子类,就先写成父类,具体情况再用子类代替(编译用父类,运行用子类),提高了代码的通用性!
编译期只能调用父类中声明的方法,运行期执行的是子类重写父类的方法,不能调用子类特有的方法(编译看左边,运行看右边),属性(编译和运行都看左边)。
虚拟方法调用
多态是运行时行为,编译时先用父类方法,运行时再动态调用属于子类的该方法。
对象类型转换
向上转型(子->父)
向下转型(父->子)
向下转型:为了调用子类特有的属性和方法。
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法? -> 向下转型:使用强制类型转换符。
Person p1=new Man();
Man m1=(Man)p1;
使用强转时,可能出现ClassCastException的异常。
Woman w1 = (Woman)p2;
w1. goShopping();
利用instanceof
,在向下转型前可以先判断:
Person p = new Student();
if (p instanceof Student) {
// 只有判断成功才会向下转型:
Student s = (Student) p; // 一定会成功
}
�