章节内容
- 类、超类和子类
- Object:所有类的超类
- 泛型数组列表
- 对象包装器和自动装箱
- 参数数量可变的方法
- 枚举类
- 反射
- 继承的设计技巧
类、超类和子类
关键字extend表示继承
已存在的类被称为超类、基类和父类,新类被称为子类、派生类或孩子类
子类通过super关键字可以调用父类的方法和域
super不同于this,它不是一个对象的引用,无法将super赋值给另一个对象变量,只是一个指示编译器调用超类方法的特殊关键字。
一个对象变量可以指示多种实际类型的现象被称为多态。
java允许将一个子类对象赋值给一个父类类型的变量。
但是一下代码会产生问题,Manager是Employee的子类:
Manager[] managers = new Manager[];
Employee[] staff = managers;
staff[0] = new Employee("Harry Hacker",...);
方法的调用
- 编译器查看对象的声明类型和方法名,获得所有可能被调用的候选方法。
- 编译器将查看调用方法时提供的参数类型。由于允许参数转换,这个过程比较复杂
- 如果是private、static、final方法或者构造器,那么编译器就可以准确地知道应该调用哪个方法,这种方式成为静态绑定
- 虚拟机根据对象的实际类型最适合的那个类的方法去调用方法
final类和方法可以阻止继承
强制类型转换可以暂时忽视对象的实际类型之后,使用对象的全部功能。
强制类型转换只能在继承层次内进行类型转换
在将超类转换成子类之前,应该使用instanceof进行检查
抽象类
抽象类使用关键字:abstract
一个类即使不含抽象方法,也可以将类声明为抽象类
抽象类不能被实例化。
受保护访问
protected关键字允许子类的方法访问超类的域和方法
Object:所有类的超类
equals方法
用于检测两个对象是否相等,在Object中默认的实现为判断两个对象是否具有相同的引用。
这样的逻辑在业务中并没有太大的用户,我们经常重写成判断两个对象的ID是否一致来判断两个对象是否相等。
如果发现类不匹配则直接返回false,不建议使用instanceof进行检测,因为这样做没有解决子类的情况
java的equals方法要求有一下特性:
- 自反性
- 对称性
- 传递性
- 一致性
- 对于任意非空的x,x.equals(null)应该返回false
hashCode方法
散列码是由对象导出的一个整型值。每个对象默认的散列码为对象的存储地址。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。
equals和hashCode的定义必须一致,如果x.equals(y)返回true,则x.hashCode()等于y.hashCode()
toString()方法
System.out.println(x),默认调用x的toString方法
泛型数组列表
ArrayList
对象包装器和自动装箱
每个基本类型都有一个与之对应的类。这些类成为包装器。
在代码中编译器自动将基本类型转换为对应类的被称为自动装箱,反之是自动拆箱。
唯一包装器类可以引用null,所以自动拆箱有可能抛出空指针异常。
参数可变方法
方法参数中的省略号代表这个方法可以接受任意数量的参数对象
枚举类
使用关键字enum定义枚举类
枚举类的比较直接使用==
枚举类可以看做是一种多例设计模式
反射
反射机制可以用来:
- 在运行时分析类的能力
- 在运行时查看对象
- 实现通用的数组操作代码
- 利用Method对象,很像C++的函数指针
Class类
虚拟机为每一种类型管理一个Class对象
Object类中的getClass()方法将返回一个Class类型的实例
利用反射分析类的能力
反射包中有Field,Method和Constructor三个类用于描述类的域、方法和构造器。
Class类中的getFields()、getMethods()、getConstructors()方法将分别返回类提供的public域、方法和构造器数组,包括超类的公有成员。
getDeclaredFields、getDeclaredMethods、getDeclaredConstrctors将分别返回类中声明的全部域、方法和构造器,不包括超类的成员。
在运行时使用反射分析对象
反射机制的默认行为受限于java的访问控制。
为了通过私有域的Field对象的get(Object)方法获取域的值,可以执行Field对象的setAccessible(true)方法。
setAccessible是AccessibleObject类的一个方法,它是Field、Method和Constructor类的公共超类。
继承的使用技巧
- 将公共操作和域放在超类
- 不要使用受保护的域
- 使用继承实现“is-a”关系
- 除非所有继承的方法都有意义,苟泽不要使用继承
- 覆盖方法时,不要改变预期的行为
- 使用多态,而非类型信息
- 不要过多使用反射