继承主要是为了实现"is-a"的概念,达到子类对超类的功能扩展
super vs this
-
this
- 引用隐私参数
- 调用该类其它的构造器
-
super
- 调用超类的方法
- 调用超类的构造器:默认会调用超类的无参构造器
- 和
this
不同,它不是一个对象的引用,所以不能将super
赋值给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字
理解方法调用
下面假设要调用x.f(args)
,隐式参数x声明为类C的一个对象:
- 编译器查看对象的声明类型和方法名,假设调用
x.f(param)
,则隐式参数x声明为C的对象。编译器会一一列举所有C中名为f的方法和超类中访问属性是public且名为f的方法 => 至此,编译器已获取所有可能被调用的候选方法 - 接下来,编译器将查看调用方法时提供的参数类型。这时有三种情况:1. 参数完全匹配,则选择该方法;2. 参数存在类型转换,需要转换后匹配;3. 匹配不到,则报错 => 至此,编译器已获得需要调用的方法名字和参数类型
- 如果是
private
方法、static方法、final方法或者构造器,那么 编译器将可以准确的指导调用哪个方法,我们将这种调用方式称为静态绑定,如果在调用的时候需要依赖隐式参数的实际类型,并且再运行时才能确定,我们称为动态绑定 - 程序运行时,如果是动态绑定,jvm会调用动态匹配的方法。由于每次方法都需要进行搜索,开销很大,所以jvm会预先为每个类都创建一个方法表,其中列出了所有方法的签名和实际调用的方法
类型强制转换
强制转换之前建议先通过instanceOf
来判断下是否合法,一般只能再集成层次内转换。不过强制转换一般都是设计的有问题,应该更多的用多态的思想
Object
所有类的超类
在Java中,只有基本类型不是对象,但是他们都有对应的包装器类型
编写一个完美的equals建议
- 显示参数命名为 otherObject,稍后需要将它转换成另一个叫做 other 的变量
- 检测 this 和 otherObject 是否引用同一个对象
if(this == otherObject) return true;
- 检测 otherObject 是否为null,如果是null,返回 false
if(otherObject == null) return false;
- 比较 this 和 otherObject 是否属于同一个类
- 如果equals的语义在每个类中有所改变,就使用 getClass 检测
if(getClass() != otherObject.getClass() ) return false;
- 如果所有的子类都拥有统一的语义(有父类的场景),就是用 instanceOf 检测
if(!(otherObject instanceOf ClassName)) return false
;
- 如果equals的语义在每个类中有所改变,就使用 getClass 检测
- 将 otherObject 转换成相应的类类型变量
- 开始比较子域
- 如果是在子类中定义,则需要调用
super.equals(other)
hashCode
- Object 中的散列码默认返回对象的存储地址
- 如果
x.equals(y)
,则x.hashCode
必须等于y.hashCode
,否则会出现相等的两个对象散列到集合的时候会被散列到不同的位置,肯定是不合理的
泛型数组列表
ArrayList.trimToSize
:可以将存储空间的大小调整为当前元素数量所需要的存储空间数目
对象包装器与自动装箱
- 尖括号中的类型参数不允许是基本类型
- 主要原因是因为java类型擦除后是Object,基本类型不是继承Object,所以需要是他们的包装类型。
- 因为都必须使用包装类型,所以ArrayList 的效率远远低于 int[]
- 自动装箱
Integer.valueOf(3)
xx.valueOf
:一般都是用于转换成xx的场景
- 装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成字节码的时候,插入必要的方法调用,jvm只是执行这些字节码
枚举类
public enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE};
-
上面的声明定义的类型是一个类,有4个实例
-
Size.SMALL.toString
将返回字符串 SMALL,toString的逆方法是valueOf
反射
Class类:Java运行时系统始终未所有的对象维护一个被称为运行时的类型标识,可以通过 下面几种方式访问:
(new Random()).getClass()
Class.forName("java.util.Random")
Random.class
- 基本类型也有:
int.class
- 基本类型也有:
可以通过 class.newInstance
获取对应类的实例,该方法默认调用调用无参构造器,如果没有无参构造器的话会抛异常
利用反射分析类的能力
Class 类中的 getFields
、getMethods
和getConstructors
方法将分别返回类提供的public域、方法和构造器数组,其中包含类的共有成员。
Class类中的 getDeclareFields
、getDeclareMethods
和getDeclaredConstructors
方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包含超类的成员
调用任意的方法
Object invoke(Object obj, Object... args)
- 静态方法obj传入null即可