继承相关知识

1.在构造器中,super调用用于显示调用父类构造器,this调用用于显示调用本类中另一个重载的构造器。二者只能取其一,且最多只能调用一次。

2.类变量的赋值-->是在构造器中super()或this()之后。

 1 public class A{
 2     private int a = 1;
 3     {
 4         a = 2;
 5     }
 6     public A(){
 7         a = 4;
 8     }
 9     {
10         a = 3;
11     }
12 }

以上代码在JVM中的执行为:

public class A{
    private int a;
    public A(){
        super();
        a = 1;
        a = 2;
        a = 3;
        a = 4;
    }
}

 

以下在”疯狂JAVA突破程序员基本功的16课“中的案例:

class Base{
    private int i = 2;
    public Base(){
        this.display();
    }
    public void display(){
        System.out.println(i);
    }
}
class Derived extends Base{
    private int i = 22;
    public Derived(){
        i = 222;
    }
    public void display(){
        System.out.println(i);
    }
}
public class Test {
    public static void main(String[] args) {
        new Derived();
    }
}

以上代码最终结果为0。

在new Derived()的时候,此对象拥有两个i的实例变量,一个是父类Base的,一个是子类Derived的,而调用父类构造方法的时候,this.display()其实是子类的方法,而此时i还未赋值,为0,谷输出结果为0。

如此时在Base类中this.display();代码之前加一句System.out.println(this.i); 最终结果为2,0

那么,这个this代表的是什么呢?

当this在构造器中时,this代表正在初始化的Java对象。在代码中this的对象应该是Derived啊,那么为什么this.i的值是2呢?这是因为<--当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际引用的对象来决定。-->

也就是说,this.i时对象为声明该变量的类型(Base),而调用方法时则是Derived。

对于这个还有一个例子可以看看:

 1 class B{
 2     int count = 2;
 3     public void display(){
 4         System.out.println(this.count);
 5     }
 6 }
 7 class D extends B{
 8     int count = 20;
 9     public void display(){
10         System.out.println(this.count);
11     }
12 }
13 public class Test{
14 
15     public static void main(String[] args) {
16         B b = new B();              
17         System.out.println(b.count);      
18         b.display();
19         
20         D d = new D();
21         System.out.println(d.count);
22         d.display();
23         
24         B bd = new D();
25         System.out.println(bd.count);
26         bd.display();
27         
28         B d2b= d;
29         System.out.println(d2b.count);
30         d2b.display();
31     }
32 }

对于b,d来说和简单,输出分别为2,2  20,20

对于db,bd.count的值为2,而bd.display()则输出20,原因则在上面加粗

对于d2b,其实与d指向同一个对象(如果输出 d2b== d 结果为true),d.count的值为20,那么d2b的值也为20么?不是的,这时d2b.count的值为2(调用display方法输出20)。也就是说,d2b指向的对象中存放着两块内存地址。同时也说明了Java继承在处理成员变量和方法时是有着不同的,变量是看编译时的对象,方法是看运行时的对象。

内存的话,当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为其父类中定义的实例变量分配内存(包括间接父类),哪怕变量名相同(只不过会隐藏)。为了在子类方法中使用父类中定义的被隐藏的变量,被覆盖的方法,可以使用super关键字。

类变量会在类初始化的阶段被初始化,是属于类的,可以直接通过类.变量名来调用,在子类中也可通过super.变量名来调用(最好使用类.变量名)。

 

你可能感兴趣的:(继承相关知识)