java继承--父类属性的存放位置

最近看java突然有一个基础的问题迷惑我很久,于是就引深一下也不知道分析是否正确和大家分享不对之处还望多多指教:

1.子类调用父类是引用吗?

2.多个子类引用的是同一个父类吗?

3.如果子类修改了父类的属性值, 对其他子类有影响的吗?

4.假如一个父类 有 3个不同的子类,那么编译完成后,实际上有几个父类的对象在jvm中(换句话,是一个子类对应一个父类,还是多个子类对应一个父类)

 

回答以上问题:

1. 在java中, 除了基本数据类型,其余的都是引用, 所以这里子类调用父类肯定是引用了!

 

2.多个子类调用的是同一个父类, 我们在java代码中可以,计算出来父类的hashcode值, 会发现是一样的!

 

3. 如果子类修改了父类的对象的属性或者方法, 肯定不会对其他子类有影响了;

     第三个解释一下:

       子类修改了父类类方法:知道java 的都知道有覆盖 这个特性, 这就是典型的覆盖, 如果有影响, 那这就不是java 的特性了,就是java 的bug 了;

       子类修改了父类的属性:其实我们可以参考方法,去理解

 

4. 如果有多个子类那么在编译完成后,会生成和子类一样多的父类的实例,因为每一个子类是编译的时候,都会有自己的一个父类引用!

 

        这里还会牵扯到一个引用问题: 那就是我们在写代码的时候,我们只写了一个父类, 在子类继承父类的时候, 我们有多个子类的时候, 继承的同一个父类吗? 上边已经回答过是同一个,那么不同子类修改了父类的属性值,应该会影响到其他子类才对,这里引用《java编程思想》中的一句话:

 为了方便理解,所以多引用些 :

写道
6 . 2 . 1 初始化基础类
由于这儿涉及到两个类——基础类及衍生类,而不再是以前的一个,所以在想象衍生类的结果对象时,可能
会产生一些迷惑。从外部看,似乎新类拥有与基础类相同的接口,而且可包含一些额外的方法和字段。但继
承并非仅仅简单地复制基础类的接口了事。创建衍生类的一个对象时,它在其中包含了基础类的一个“子对
象”。这个子对象就象我们根据基础类本身创建了它的一个对象。从外部看,基础类的子对象已封装到衍生
类的对象里了。
当然,基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通过调
用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,Java 会自动插
入对基础类构建器的调用

 

对于以上这句话可以比较理解可能更容易些:

我们更具java可以想想,如果要在一个类中引用其他的类中的属性和方法应该怎么做, 正常我们使用的是“组合”(即在这个类中new 出其他类型的 属性)

public class Cat2 {
	public Animal animal = new Animal();

	public void print() {
		System.out.println("super:"
				+ this.getClass().getSuperclass().getName().hashCode());
		animal.print();
		// System.out.println("name hashcode:" + name.hashCode());
		animal.age = 10;
		animal.name = "mimi";
		System.out.println("name hashcode:" + animal.name.hashCode());
		animal.print();
	}
}

public class Animal {
	public String name;
	public int age;

	public void print() {
		System.out.println("name:" + name + "\tage:" + age);
	}
}

 

 

我们也可以采用 继承的方式:

public class Cat extends Animal {

	public void print() {
		System.out.println("super:"
				+ this.getClass().getSuperclass().getName().hashCode());
		super.print();
		//System.out.println("name hashcode:" + name.hashCode());
		age = 10;
		name = "mimi";
		System.out.println("name hashcode:" + name.hashCode());
		super.print();
	}
}

 

 

测试代码:

 https://github.com/younglibin/mytestcode/tree/master/src/com/younglibin/study/extendsTest/Client.java

我们在理解组合的时候比较容易理解,在jvm编译cat2 这个类的时候, 我们肯定知道,animal 作为cat2 的属性引用被编译的cat2 中了(即: Fields_count 中), 那么继承在编译的时候是怎么找到这个animal 呢, 在编译cat的时候, 他会首先找到 看 animal是否被编译,编译之后就会cat中包含一个基础类的”子对象“,(即:Supper_class 中);

 

进过上述说明:我们可以理解,其实不管是组合还是继承, “子类对象”都拥有了“父类对象的一个实例的引用”所以如果你有多个子类的话, jvm 在编译的时候,就会编译出来多个父类实例, 而不是我们在写java 代码的时候,我们写了一个父类, 看来是jvm帮我们把重复的事情做了!

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值