动手动脑——继承与多态

继承条件下的构造方法调用

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关键字来访问它。 如果子类被当作父类使用,则通过子类访问的字段是父类的!

原文地址:https://www.cnblogs.com/dream0-0/p/9925136.html