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

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 +
                '}';
    }
}

先看一段测试代码:

@Test
public 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等修饰的方法访问他们。

  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值