Java类的初始化、继承

y上面的几个关键词都是Java中比较常见也比较混淆的几个。

Java类的初始化

首先是Java的cinit方法,这个方法有Java虚拟机加载类时自动执行,这个方法会收集所有的静态变量及静态块执行,并且仅执行一次(按照顺序执行)。

其次是类中成员变量的初始化。

然后是类中的初始化块(如果有多个则按照顺序执行)。

最后是类的构造方法。

如果类有父类,则先按照上面的顺序初始化父类。

Java的继承

这一部分涉及比较多的是多态。而多态又涉及到方法的重写。关于重写的相关内容之前在博客中已经涉及了。这里说说变量的“重写”。之所以在重写上加引号,是因为变量是没有重写的。看下面的代码:

public class Test {
    public static void main(String[] args) {
        Base b = new Sub();
        System.out.println(b.x);
    }




}


class Base{
    int x = 10;

    public Base(){
        this.printMessage();
        //printMessage();
        x = 20;
    }

    public void printMessage(){
        System.out.println("Base.x = "  + x);
    }
}


class Sub extends Base{
    int x = 30;

    public Sub(){
        this.printMessage();
        x = 40;
    }


    public void printMessage(){
        System.out.println("Sub.x = " + x);
    }
}

如果运行上面的代码,结果为:

Sub.x = 0
Sub.x = 30
20

至于为什么是Sub.x应该比较清楚了,java是动态单分配,方法调用只根据对象的实际类型,即使是调用了父类的方法,如果这个父类方法中有被重写的方法,那还是调用子类的重写方法。

为什么有两次Sub.x输出呢?因为在初始化子类时,虚拟机会保证先初始化父类。

然后就是最重要的x 的值了。为什么有0,有30,还有20呢?在Java中如果在子类中声明了和父类相同名字的变量,以上面的代码为例,变量x 实际上会有两份值,一个是父类的x,一个是子类的x。如果在子类中获取x的值,那就会取子类的x,除非特除声明用super.x

所以上面代码的执行顺序为:

1.调用Sub类的构造方法
2.在执行Sub类初始化前,先初始化Base类
3.在Base类中x为10,调用printMessage()方法,实际调用了子类的printMessage方法。
4.子类的printMessage方法输出子类x的值,由于子类的x还没有初始化,所以输出0.
5.父类的x为20.
6.子类的初始化过程,子类的x为30.
7.子类的构造方法,输出30.
8.Main方法的输出,输出Base的x值。

引用别人博客的一句话:

其实就是可见性的问题。 父类和子类的变量是同时存在的,即使是同名。 子类中看到的是子类的变量,父类中看到的是父类中的变量。
它们互相隐藏,而同名的方法则是实实在在的覆盖。

如A x = new B(); x是一个B,也是一个A, 那么调用方法时,是根据对象的实际类型调用的,
实际类型是B,所以永远调用子类的方法。

而访问成员变量就不同了,它是B时,访问的是子类的成员变量, 转型为A的话,访问的就是父类的成员变量了。

总结

个人认为在出现变量隐藏(类型可以不同,但不可以private的)的情况下,如果是直接调用变量,那么得到的值跟外观类型有关。否则与方法在的类有关。

最后再写一个例子:

package test;



public class Test3 {
    public static void main(String[] args) {
        Base b = new Sub();
        System.out.println(b.x);
        System.out.println(b.get());
    }




}


class Base{
    int x = 10;

    public Base(){
        printMessage();
        printMessage2();
        x = 20;
    }
    public int get(){
        System.out.println("Base get");
        return x;
    }

    public void printMessage(){
        System.out.println("Base.x = "  + x);
    }

    public void printMessage2(){
        System.out.println("v2---Base.x = " + x);
    }
}


class Sub extends Base{
    int x = 30;

    public Sub(){
        printMessage();
        x = 40;
    }

    public int get(){
        System.out.println("Sub get");
        return super.get();
    }
    public void printMessage(){
        System.out.println("Sub.x = " + x);
    }
}

运行结果是:

Sub.x = 0
v2---Base.x = 10
Sub.x = 30
20
Sub get
Base get
20
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值