1 抽象
抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
2 封装
把数据和行为隐藏,只能通过暴露的接口访问数据。
3 继承
通过扩展一个类来建立另一个新的类。
3.1 慎用继承
- 将公共操作和域放在超类。
- 不要使用受保护的域。
- 使用继承实现"is-a"。
- 除非所有继承的方法都有意义,否则不要使用继承。
- 在覆盖方法时,不要改变预期的行为。
- 使用多态,而非类型信息。
- 不要过多地使用反射。
3.2 强制类型转换
只能在继承层次内进行类型转换。
在将超类转换成子类之前,应该使用 instanceof 进行检查。
- 上溯造型(Upcasting):把衍生类型当作它的基本类型处理
- 下溯造型(Downcasting):向下转型,超类可用子类置换。
3.3 重写(override)
存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。
为了满足里式替换原则,重写有以下三个限制:
- 子类方法的访问权限必须大于等于父类方法;
- 子类方法的返回类型必须是父类方法返回类型或为其子类型。
- 子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。
使用 @Override 注解,可以让编译器帮忙检查是否满足上面的三个限制条件。
在调用一个方法时,先从本类中查找看是否有对应的方法,如果没有再到父类中查看,看是否从父类继承来。否则就要对参数进行转型,转成父类之后看是否有对应的方法。总的来说,方法调用的优先级为:
- this.func(this)
- super.func(this)
- this.func(super)
- super.func(super)
3.4 重载(overload)
存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。
应该注意的是,返回值不同,其它都相同不算是重载。
4 多态
一个对象变量可以指示多种实际类型的现象被称为多态(polymorphism)。
Java 实现多态有三个必要条件:继承、重写、上溯造型。
虚拟机预先为每个类创建了一个方法表(method table),其中列出了所有方法的签名和实际调用的方法。
4.1 动态绑定
在运行时能够自动选择调用哪个方法的现象称为动态绑定。
- 编译器会列举类方法表中同名方法,和超类方法表中同名且为 public 的方法。
- 编译器重载匹配参数类型,若有完全匹配的就选择,没有就匹配允许类型转换的方法,如果这样还是不能找到匹配项,编译器就会报错;同时如果找到多于一个匹配项,编译器也会报错。
4.2 静态绑定
如果是 private,static,final 方法或者构造器,那么编译器可以明确地知道该调用哪个方法,这种调用方式成为静态绑定。