继承条件下的构造方法调用
class Grandparent { Grandparent(){ System.out.println("GrandParent Created."); } Grandparent(String string) { System.out.println("GrandParent Created.String:" + string); } } class Parent extends Grandparent{ Parent(){ //super("Hello.Grandparent."); System.out.println("Parent Created"); //super("Hello.Grandparent."); } } class Child extends Parent { Child(){ System.out.println("Child Created"); } } public class TestInherits { public static void main(String args[]){ Child c = new Child(); } }
上述程序中主方法只创建了一个Child类的对象,在对象创建时默认使用了super()方法调用父类的无参构造方法。若是只将第一个//super("Hello.Grandparent.");解注释,则运行结果中第一行会变成GrandParent Created.String:Hello.Grandparent.。而只将第二个解注释,则编译器会报错。所以,通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。
类型转换问题
class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} class Test { public static void main(String[] args) { Mammal m=null; Dog d=new Dog(); Cat c=new Cat(); m=d; d=m; //× d=(Dog)m; d=c; //× c=(Cat)m; } }
子类对象可以直接赋给基类变量。 基类对象要赋给子类对象变量,必须执行类型转换, 其语法是: 子类对象变量=(子类名)基类对象名; 如果类型转换失败,Java会抛出ClassCastException异常。
可以使用instanceof运算符判断一个对象是否可以转换为指定的类型: Object obj="Hello"; if(obj instanceof String) System.out.println("obj对象可以被转换为字符串");
public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); parent.printValue();//100 Child child=new Child(); child.printValue();//200 parent=child; parent.printValue();//200 parent.myValue++;
System.out.println(parent.myValue); parent.printValue();//200 ((Child)parent).myValue++; parent.printValue();//201 } } class Parent{ public int myValue=100; public void printValue() { System.out.println("Parent.printValue(),myValue="+myValue); } } class Child extends Parent{ public int myValue=200; public void printValue() { System.out.println("Child.printValue(),myValue="+myValue); } }
上述程序中,主方法中存在将子类对象赋给基类对象,所以会出现明明调用的基类对象的方法,运行结果中却变成了调用子类对象的方法的情况。将子类对象赋给基类对象过后,又出现了parent.myValue++;这一句,实际上这一句是将基类对象的myValue值加一(由后边输出基类对象的myValue值可以看出),但由于基类对象此时为子类型,所以调用的方法并不是基类对象自己的方法,因此会出现结果截图中第五行所示的情况。((Child)parent).myValue++;这一句中,由于将基类对象强制转换为子类型再进行加法运算,所以实际上是子类对象的myValue值加一。
当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。 如果子类被当作父类使用,则通过子类访问的字段是父类的!