子类实例化是否会实例化父类?不会

来源:互联网 发布:淘宝买手机靓号靠谱吗 编辑:程序博客网 时间:2024/05/21 22:45

java中对象,与类在内存方面的理解,使得对象与类的概念具体点

  首先关于类,我们可以把它当成一个瓶子模具,这里的模具只是用它的概念,不需要带入真正的模具(因为瓶子没有模具),当我们在
java中使用new来新建一个对象bottle时,可以想象成用这个模具去造了一个新瓶子,这个新瓶子是纯粹一个瓶子,什么花
纹都没有,我们当成这个就是这个bottle的属性的初始值,然后我们开始对这个新的对象bottle赋值,这个过程就像是在这个新的瓶子上面描上花纹的过程。

  那么抽象类像什么呢?抽象类,我们把它想象成半个瓶子模具,残缺的,不完整,我们不能使用它去造一个新的瓶子,也就是new一个新的对象,那么如何才能让他变成一个完整的瓶子模具呢?

  我们会把它补全使它成为一个完整的瓶子模具,也就是在这个半个瓶子模具的基础上,补全成为一个新的瓶子模具,就像是java的extends,拥有抽象父类的属性,方法,同时实现抽象父类的抽象方法。

  继续,Interface像什么呢?花纹,纯粹的花纹,当把这些花纹刻在模具上时,使用模具造出来的瓶子,也就有了这些花纹,就像是java中的类实现接口。

  现在谈谈子类继承父类时,private属性和方法,先只谈谈private属性

/** * Created by 西皮 on 2017/9/17 14:23. */public class FatherClass {    private String name;    private int age;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;        System.out.println(this.toString());    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;        System.out.println(this.toString());    }    @Override    public String toString() {        return "FatherClass{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}

子类父类多一个fair

/** * Created by 西皮 on 2017/9/17 14:23. */public class SonClass extends FatherClass{    private String fair;    private String name;    private int age;    public SonClass(){    }    public String getFair() {        return fair;    }    public void setFair(String fair) {        this.fair = fair;        System.out.println(this.toString());    }    @Override    public String toString() {        return "SonClass{" +                "fair='" + fair + '\'' +                ", name='" + name + '\'' +                ", age=" + age +                '}';    }}

先看一段测试代码:

@Testpublic void testF(){    SonClass son = new SonClass();    FatherClass father = new FatherClass();    father.setName("father");    father.setAge(50);    son.setName("son");    son.setAge(18);    son.setFair("有头发");    System.out.println(son.toString());    System.out.println(father.toString());}

结果是:

这个可以说明在堆内存中,这个son指向的对象,里面应该是有两个name,和两个age的一份是从父类继承过来的,一份是自己的,而我们的toString方法,打印的是本类的属性值。

那么当我们加一句System.out.println(son.getName()+son.getAge());,可以很明显得到son18的输出

这里必须说明的是,父类在子类实例化过程中是并没有被实例化的

public SonClass(){        super();//调用父类的构造器,但只是用来初始化属性        System.out.println(this.hashCode());        System.out.println(super.hashCode());        System.out.println(super.equals(this));}public FatherClass(){    System.out.println(this.hashCode());    System.out.println(super.hashCode());    System.out.println(super.equals(this));}

这里分别在子类和父类中加入构造器,然后SonClass son = new SonClass();去除多余的输出,可以看到如下输出:

这说明this和super都指向同一对象,这里的hashCode值是jvm根据对象在内存中的地址生成的,是可以一一对应的。也就是,在子类构造器中,调用的super(),只是为了给继承父类而来的属性初始化

这里我们补充一下jvm中的new指令的过程:

  jvm虚拟机遇到一条new指令是如何工作的,遇到一条new指令,首先去检查这个指令的参数
是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。

  在类加载检查通过后,接下来虚拟机将为新生对象分配内存,在内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),接下来,虚拟机要对对象进行必要的设置。。。。。。

  在上面的工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但是这里的属性都是默认属性,
现在我们需要把对象按程序员的意愿初始化,也就是执行new指令之后会接着执行init方法。

以上是《深入理解java虚拟机——jvm高级特性和最佳实践》中对对象的创建的描述。

而在《Thinking in Java》94面中:无法阻止自动初始化的进行,他将在构造器被调用之前发生。

猜测一下,可以能java中构造函数是在new指令执行完毕之后,才进入构造函数,这样构造函数也就是按程序员的意愿初始化了。

总结一下,java中new SonClass并没有实例化父类,只是调用父类的构造方法初始化了,子类从父类继承来的属性,这个调用是子类的对象调用的父类的构造方法,而子类自己的构造方法完成对自己属性的初始化(这里的初始化是指我们在内存分配完了,虚拟机初始化之后,我们按自己的要求进行的初始化)

而private方法,也是和private属性一样的道理。

也就是子类其实是继承了父类所有的属性和方法,只是private的不能直接访问而已,可以通过public等修饰的方法访问他们。

原创粉丝点击