1、 类、超类和子类:关键字extends表明正在构造的新类派生自一个已经存在的类;已经存在的类称为超类(也称:父类、基类),新类称为子类(也称:派生类)[C++中的继承与此类似, 但是用“:”表示继承];
2、 Java中的继承关系都是公有继承[C++中的继承分公有继承、保护继承和私有继承];
3、 子类继承了超类的方法和域;
4、 设计的时候,通常将通用的行为和公共的属性放置在超类中,而将某些特殊的属性和行为放置在子类中;
5、 超类中有些通用的方法不一定完全适合于子类,子类可以提供完全相同的方法来覆盖超类的方法;
6、 在子类的方法中如果要调用超类的方法,可以通过super.方法名()调用,必须作为该方法的第一条语句;
7、 super和this是不同的概念, super不是一个对象的引用,不能将super赋值给另外一个对象变量,它只是一个指示编译器调用超类方法的关键字[C++中用超类的名字加:: 加方法名]。
8、 子类构造器中需要调用超类构造器时,用super(参数列表);如果子类构造器没有显示调用超类的构造器,则将自动调用超类默认构造器[C++中子类构造器调用超类的构造必须在初始化列表中,用超类名(参数列表)]。
9、 一个变量可以引用多种实际类型的现象被称为多态,在运行时自动选择调用哪个 方法的现象称为动态绑定。[C++中,动态绑定需要声明虚函数,Java中不需要,如果不希望一个方法具有虚拟特征,可以使用final关键字修饰];
10、 一个公共类派生出来的所有类的集合被称为继承层次;在继承层次中,某个类到其祖先的路径称为该类的继承链[C++中支持多继承,即一个类可以有多个超类,Java中不支持多继承,但是可以实现多接口,参考下一章];
11、 Java中的对象变量是多态的,C++中,对象的引用类型和指针类型是多态的;
12、 不能将一个超类的对象赋值给子类的对象变量;
13、 类方法调用过程:
1) 编译器查看对象的声明类型和方法名;根据对象类型和方法名列出所有可能的方法(可能存在重载的方法);
2) 编译器查看调用方法时提供的参数类型,查找完全匹配的参数的方法, 这个过程为重载解析;如果没有找到完全匹配的方法或者经过参数类型转换后有多个方法与之匹配,则会报错;
3) 如果是private方法,static方法,final方法或者构造器,那么编译器将可以准确的知道应该调用哪个方法,这个过程为静态绑定;相反调用方法依赖于隐藏参数的实际类型,并且在运行时实现动态绑定;
4) 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类方法。每次调用的方法都要进行搜索, 时间开销很大,因此虚拟机预先为每个类创建了一个方法表[C++与之类似,称虚表/虚函数表];
14、 在覆盖一个方法时,子类方法的可见度不能低于超类方法。
15、 阻止继承, 不希望扩张某个类时,用final修饰类;也可以阻止类中某一个/一些方法不被继承,也用final修饰, final修饰的数据域表示域在初始化后,不能被修改,final修饰的类,其域也不能被修改;
16、 强制类型转换
1) 只能在继承层次内进行类型转换;
2) 在将超类转换成子类之前, 应该使用instanceof检查对象的类型,确定是否能转换;
3) 如果试图在继承链上进行向下的类型转换, 将产生一个ClassCastException异常;
4) 如果x为null, x instanceof C 不会产生异常,返回结果为false;
5) C++中强制类型转换, 如果转换不成功,则返回一个空指针;
17、 抽象类
1) 抽象是对象设计中的最重要, 将相类似的对象的公共属性或者功提取出来,放到最顶层的祖先类;
2) 抽象方法,用abstract修饰,表示这个方法在该类中不需要实现,充当占位符,由子类来实现;
3) 抽象类,除了包含抽象方法外,还可以包含其它方法和数据域;
4) 类即使不包含抽象方法,可以将类声明为抽象类;
5) 抽象类不能被实例化,就是不能用new 创建一个抽象类的对象,但是定义抽象类数组变量时,可以使用new ;抽象类的对象变量可以引用一个子类的对象;
6) C++中,在函数声明的后面加上“=0”表示抽象方法,C++中称纯虚函数, 只要有一个纯虚函数,那么该类就是一个抽象类,Java中可以使用abstract关键定义抽象类;
18、 受保护访问
1) 如果需要在子类中直接访问超类的方法或者数据域,而不允许其它类访问,则可以使用protected修饰;
2) 尽量不要对数据域使用protected;
3) C++中的protected比Java中的protected更安全, Java中的protected对包和所有的子类可见;
19、 Java中可见度修饰符
修饰符 | 可见度 |
public | 所有类都可见 |
protected | 对所有子类和本包中可见 |
默认 | 没有标明任何修饰符,表示本包中可见 |
private | 仅对本类可见 |
20、 Object类,所有类的根类
1) Java中,除了基本类型外,其它都是对象;Object类是所有类的超类,但是不需要用户显示extend继承自Object类;
2) 判断对象是否相等(equals),要注意这与对象之间用==判断是否相等是不同的,equals判断的是两个对象的类和属性是否相同,==判断的是对象是否是同一个对象(类和对象的地址);
3) Java语言规范要求equals方法所具备的特性;
A) 自反性:对于任何非空对象x,x.equals(x)返回true;
B) 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也返回true;
C) 传递性:对于任何引用x,y和z,如果x.equals(y)返回true,y.equals(z)也返回true,那么x.equals(z)将返回true;
D) 一致性:如果x和y引用的对象没有任何变化,返回调用x.equals(y)返回结果应该相同;
E) 非空性:对于任何非空引用x, x.equals(null)应该返回false;
4) 编写equals的建议:
A) 显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量;
B) 检测this与otherObject是否引用同一个对象;
C) 检测otherObject是否为null,如果为null,返回false;
D) 比较this与otherObject是否是同一个类;
E) 将otherOjbect转换为相应的类类型变量;
F) 比较所有的属性域,如果属性是基本类型用==比较,如果是对象类型,则使用equals比较;如果子类充定义了euqals,则在子类中需要调用超类的equals方法;
5) hashCode方法
A) 散列码(hashCode)是由对象导出的一个整数值,并且没有规律可循;
B) hashCode 方法应该返回一个整型值(可以是负数),并合理地组合实例域的散列码,以便能够让各不相同的对象产生的散列码更均匀;
C) 如果重新定义了equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入散列表中;
6) toString方法
A) toString方法用于返回对象值的字符串;
B) 遵循的格式:类名称,[数据域];(类名称获取方法getClass().getName())
C) 作用:当对象与字符串用+拼接时,Java自动调用toString方法;
D) 调试作用,当调试程序的时候,需要获取对象的数据域和状态信息,toString方法可以方便的打印出来;
7) Arrays类
A) Arrays类静态的equals方法可以检查两个数组的元素是否相等;
B) Arrays类静态的hashCode方法计算一个数组的散列码,这个散列码由数组元素的散列码组成;
C) Arrays类静态的toString方法可以返回数组中每个元素的toString(对象定义了toString);如果是多维数组可以使用Arrays.deepToString();