基类与派生类之间的强制类型转换
public class Test {
public static void main(String[] args) {
Grandfather grandfather = new Grandfather();
Father father = new Father();
Son son = new Son();
Grandfather grandfather1 = (Grandfather) father;
father.act();
除了主函数外我们定义了一个Grandfather和Father和Son三个类,其中Father这个 类里有个其余两个类没有的act方法,接下来我们用Grandfather定义了一个对象grandfa,并将father的值赋值给他,并对father做了做了一个类强转成父类,当我们对father调用act方法时,可以进行调用输出,但是当我们用grandfather1对其进行调用act方法时无法调用。不是将father赋值给grandf1了嘛,为什么不可以。我们再对这条赋值语句做进一步的讨论,首先我们定义了一个grandfather1的对象,并将father赋值给grandfather1.我们知道对象的本质就是四字节的指针,而father则是Father类生成的该类长度的空间,即grandfat1指向father空间,所以grandfather用的仍然是father里的成员,但是却无法使用father里独有的成员和方法,所以才会出现grandfa1无法调用father里的act方法。
有以下结论 :
父类决定了能够引用的成员和方法,子类决定了其成员和方法具体的值。
对象的类型约束了对象所能引用的方法和成员,但是不能更改成员或者方法的本质内容;对于方法,强转不能改变其所实际指向的代码的首地址。
Object
一切类的共同基类 ——Object
可以看到,因为所有的类都继承于Object类,所以任何子类都可以 用Object类的方法。
这些方法里很多都是可以覆盖的。接下来主要讲equals()方法和toString()方法的覆盖
toString
此步我们对对象进行输出 ,得到输出的结果是:地址
同时,更加说明对象的本质是指针。
其实对father输出,JVM会自动调用toString()方法,我们可以在父类中覆盖Object类的toString()方法来改变输出的结果,代码如下
输出是 hello
equals
其具体作用是对八大基本类型数值大小的比较。类是一种复杂的数据类型,类的对象本质是首地址,所以对于类对象内容的大小比较是不能用关系运算符的。
Father father1 = new Father(10,20);
Father father2 = new Father(10,20);
System.out.println(father1 == father2);
输出结果是false,当然是false啦!因为new出来的两个实例空间不同,所以两个对象的值不同,所以对对象做相等比较肯定是错的啊,因为他们指向的空间当然不是同一个空间啦!
@Override
public boolean equals(Object arg0) {
if(null == arg0) {
return false;
}
if(this == arg0) {
return true;
}
if(!(arg0 instanceof Father)) {
return false;
}
Father tmp = (Father)arg0;
return this.num == tmp.num&&this.num2 == tmp.num2;
}
此处我们覆盖了Object的equal()方法。首先我们想到相等比较会是两个参数之间的比较,但是又为什么此处只传递了一个参数,其实有这个想法的根本原因是c语言的固有思维,在Java里,我们的方法只有通过对象来调用,那么也就是说当调用的时候我们已经有了一个参数了,那么我们只需要另外的参数即可,所以我们传入了一个参数,而对这个参数来说,他是Object类型,但是这个例题里怎么能将Father类型和Object类型比较,因为Object里根本就没有num成员,那就只有将这个Object类型的对象转换成Father类型的对象