`
younglibin
  • 浏览: 1193167 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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
4
分享到:
评论
7 楼 pjwqq 2015-02-12  
“子类对象”都拥有了“父类对象的一个实例的引用”
我晕,应该是
“子类对象”都拥有了“父类对象.class 的引用”
6 楼 edr_ 2014-02-11  
younglibin 写道
edr_ 写道
你好,有个小问题:创建一个子类对象是否会同时创建一个父类对象?我觉得是对象的hashcode。我的测试代码,测试结果附上。


肯定会创建的一个父类的实例, 具体看1楼的回复


如果父类对象是抽象类的话,父类对象哪里来?子类对象创建的时候只是调用父类的构造方法,并未创建父类对象。
5 楼 younglibin 2014-02-11  
edr_ 写道
你好,有个小问题:创建一个子类对象是否会同时创建一个父类对象?我觉得是对象的hashcode。我的测试代码,测试结果附上。


肯定会创建的一个父类的实例, 具体看1楼的回复

4 楼 edr_ 2014-02-10  
你好,有个小问题:创建一个子类对象是否会同时创建一个父类对象?我觉得是对象的hashcode。我的测试代码,测试结果附上。
class F {
	F() {
		System.out.println("F build...");
	}
}

class S1 extends F {
	S1() {
		System.out.println("S1 build...");
		System.out.println(this.hashCode()+"--"+super.hashCode());
		System.out.println("Super class:"+this.getClass().getSuperclass().hashCode());
	}
}

class S2 extends F {
	S2() {
		System.out.println("S2 build...");		
		System.out.println(this.hashCode()+"--"+super.hashCode());
		System.out.println("Super class:"+this.getClass().getSuperclass().hashCode());
	}
}

public class Test {
	public static void main(String[] args) {
		new S1();
		new S2();
	}
}
//结果
F build...
S1 build...
14576877--14576877
Super class:12677476
F build...
S2 build...
33263331--33263331
Super class:12677476
3 楼 timer_yin 2014-02-08  
对基础加深理解,谢谢分享
2 楼 younglibin 2014-02-07  
xz5041118 写道
我们可以理解,其实不管是组合还是继承, “子类对象”都拥有了“父类对象的一个实例的引用”所以如果你有多个子类的话, jvm 在编译的时候,就会编译出来多个父类, 而不是我们在写java 代码的时候,我们写了一个父类, 看来是jvm帮我们把重复的事情做了!

“子类对象”都拥有了“父类对象的一个实例的引用”,这个是对的。
但是“jvm 在编译的时候,就会编译出来多个父类, 而不是我们在写java 代码的时候,我们写了一个父类, 看来是jvm帮我们把重复的事情做了!”就有问题了。
jvm不会去编译父类,只会加载父类的class文件,而且只会有一个,你想表达的意思应该是在一个父类有多个子类,那么在创建子类对象的时候,也会创建多个父类的对象吧。

多谢指点,是这么理解的, 可以说成是多个父类的实例吧。
1 楼 xz5041118 2014-02-07  
我们可以理解,其实不管是组合还是继承, “子类对象”都拥有了“父类对象的一个实例的引用”所以如果你有多个子类的话, jvm 在编译的时候,就会编译出来多个父类, 而不是我们在写java 代码的时候,我们写了一个父类, 看来是jvm帮我们把重复的事情做了!

“子类对象”都拥有了“父类对象的一个实例的引用”,这个是对的。
但是“jvm 在编译的时候,就会编译出来多个父类, 而不是我们在写java 代码的时候,我们写了一个父类, 看来是jvm帮我们把重复的事情做了!”就有问题了。
jvm不会去编译父类,只会加载父类的class文件,而且只会有一个,你想表达的意思应该是在一个父类有多个子类,那么在创建子类对象的时候,也会创建多个父类的对象吧。

相关推荐

Global site tag (gtag.js) - Google Analytics