Create by westfallon on 8/9
继承
- 利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用这些类的方法和域,在此基础上还可以添加一些新的方法和域,以满足新的需求
类、超类和子类
- Java 中 extends 关键字表示继承
- Java 与 C++ 定义继承类的方式十分类似。Java 用关键字 extends 代替了 C++ 中的冒号( : )。在 Java 中,所有的继承都是公有继承,而没有C++中私有继承和保护继承
- extends 表明正在构造的新类派生于一个已经存在的类。已存在的类称为超类(superclass)、基类(base class)或父类(parent class);新类称为子类(subclass)、派生类(derived class)或孩子类(child class)
super关键字
- 调用超类的方法
- 调用超类的构造器
继承层次
- 由一个公共超类派生出来的所有类的集合被称为继承层次(inheritance hierarchy)
- 在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链
多态
- 一个对象变量可以指示多种实际类型的现象叫做多态(polymorphism)
- 在Java中,子类数组的引用可以转换成超类数组的引用,而不需要采取强制类型转换
动态绑定
- 在运行时能够自动地选择调用哪个方法的现象叫做动态绑定(dynamic binding)
- 调用对象方法的执行过程:
- 编译器查看对象的声明类型和方法名
- 编译器将查看调用方法时提供的参数类型,如果函数名与参数类型完全匹配,就选择这个方法。这个过程叫做重载解析
- 如果是private方法、static方法、final方法或者构造器,编译器可以准确地知道应该调用哪个方法,这种调用方式叫做静态绑定(static binding)。与此对应的是,调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定
- 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与所引用对象的实际类型最合适的那个类的方法
- 动态绑定有一个非常重要的特性:无需对象有的代码进行修改,就可以对程序进行扩展
- 在覆盖一个方法的时候,子类方法不能低于超类方法的可见行。特别是,如果超类方法是public,子类方法一定要声明public
final类和方法
- 不允许扩展的类称为final类
- 类中的特定方法也可以被声明为final。如果这样做,子类就不能覆盖这个方法,final类中所有方法自动称为final方法
- 对于final域来说,构造对象之后就不允许再改变它们的值了。不过,如果将一个类声明为final,只有其中的方法自动地成为final,而不包括域
- 将方法或类声明为final的主要目的是:确保它们不会再子类中改变语义
类型转换
- 将一个子类的引用赋给一个超类变量,编译器是允许的。但将一个超类引用赋给一个子类变量,必需进行类型转换
- 在进行类型转换之前,应该先查看一下能否成功转换,可以使用 instanceof 运算符实现
抽象类
- 包含一个或多个抽象方法的类本身必须被声明为抽象的
- 抽象方法充当着占位的角色,它们的具体实现在子类中
- 抽象类不能被实例化
Object 类
- 如果没有明确的指出超类,Object类就被视为是这个类的超类
equals方法
- Object类中的equals方法用于检测一个对象是否等于另外一个对象
- equals特性:
- 自反性:对于任何非空引用x,x.equals(x)应当返回true
- 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应当返回true
- 传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true
- 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应当返回同样的结果
- 对于任意非空引用x,x.equals(null)应该返回false
- 编写equals方法的建议
- 显式参数命名为otherObject
- 检测this与otherObject是否引用同一对象
- 检测otherObject是否为null
- 比较this与otherObject是否属于同一个类,可以使用getClass检测
- 将otherObject转换为相应的类型变量
- 对所有域进行比较
hashCode方法
- JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做 Object的比较或者取这个对象的时候,它会依据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。详细过程是这样:
new Object(),JVM依据这个对象的Hashcode值,放入到相应的Hash表相应的Key上,假设不同的对象确产生了同样的hash值,也就是发 生了Hash key同样导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将全部产生同样hashcode的对象放到这个单链表上去,串在一起。
比较两个对象的时候,首先依据他们的 hashcode去hash表中找他的对象,当两个对象的hashcode同样,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一 定在这个key上的链表上。
那么此时就仅仅能依据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.
- 两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象。
反射
- 反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操控Java代码的程序
- 能够分析类能力的程序称为反射(reflection),可以用来:
- 在运行中分析类的能力
- 在运行中查看对象
- 实现通用的数组操作代码
- 利用Method对象
Class类
- 程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行
- 可以通过专门的Java类访问这些信息,保存这些信息的类称为Class
- 最常用的Class方法是getName,返回类的名字
- 可以调用静态方法forName获得类名对应的Class对象
继承设计的技巧
- 将公共操作的域放在超类
- 不要使用受保护的域
- 使用继承实现“is-a”关系
- 除非所有继承的方法都有意义,否则不要使用继承
- 在覆盖方法时,不要改变预期的行为
- 使用多态,而非类型信息
- 不要过多地使用反射