关于java子类继承来的属性与方法究竟是完全复制还是共用使用
关于java子类继承来的属性与方法究竟是完全复制还是共用使用
今天在学习java的面向对象时,无意间发现一个问题。
public class testEquals{
public static void main(String[] args){
Child cd1 = new Child();
cd1.f();
}
}
class Father{
public int value;
public void f(){
value = 100;
System.out.println("classFatherValueIs:"+value);
}
}
class Child extends Father{
public int value; //请看这里
public void f(){
super.f();
value = 200;
System.out.println("classChildValueIs:"+value); //输出
System.out.println(value);
System.out.println(super.value+"super.value");
}
}
/**
result:
classFatherValueIs:100
classChildValueIs:200
200
100super.value
**/
当Child类在继承Father类时,子类有重新声明value变量,在Child.f()内对value变量的值进行修改并不会改变父类Father.f()的值。
断点debug:父类子类均有自己的值
而当我将子类的value变量声明去掉后,情况变得和想象中就不太一样了,以往我所认知的继承应该是将非private的成员统统复制过来,并于父类互补干扰。但实际并不是这个样子。
当去掉子类的类型声明
package cn.sxt.oop;
public class testEquals{
public static void main(String[] args){
Child cd1 = new Child();
cd1.f();
}
}
class Father{
public int value;
public void f(){
value = 100;
System.out.println("classFatherValueIs:"+value);
}
}
class Child extends Father{
public void f(){
super.f();
value = 200;
System.out.println("classChildValueIs:"+value);
System.out.println(value);
System.out.println(super.value+"super.value");
}
}
/**
result:
classFatherValueIs:100
classChildValueIs:200
200
200super.value
父类的value值随着子类一起改变了。虽然没有显示的在子类中声明value变量,但通过继承,应该是互不干扰才是,为什么在子类定义value,父类的值也改变了。
断点debug:此时父类的value也受到了子类的影响变成了200
子类究竟时如何被实例化出来的?
以上面child类为例,Child的父类是Father类,而father类继承所有类的老子Object类。也就是说实例化一个Child类,首先要生成一个Object类,father类继承Object类中被特别定义的成员,并根据要求生成Father实例,Child类再继承Father实例生成child对象。也就是说如果想单独生成Child类,Father于Object类也再咱们不知情的情况下生成了。
大胆推测一下:
继承并不是单纯的复制父类代码。在子类中没有对父类的相同的成员名进行单独定义时,子类继承来的成员其实只是对父类成员的引用。当单独去进行声明,即使没有重新去定义逻辑,也相当于覆盖了继承来的属性或方法。
如果继承是单纯的复制代码,那么子类所占的内存需要和父类一样打,甚至更大。所以相同的部分向上引用应该就是一个很好的办法。
后来在科普看到了类似的解答,和我猜的大致差不多:
继承是复制还是共用?例如 Dog类继承Animal类,在Dog中的属性修改,Animal中的属性也会一起改变吗?如果用Dog和Animal分别实例化对象,dog和animal,这两者的属性是公用还是各占内存,毫无关系?另外要对子类继承的属性赋值,通过super(),最终跳到父类构造器,此时,是不是创建了一个父类对象?
1、共用更恰当,因为父类的一些私有方法和私有属性是不会被继承的,继承之后,子类可以共用父类的公有属性和公有方法,,
2、Dog中如果没有重新定义父类已有的同名属性,则修改公有属性就是修改父类的公有属性,即父类的属性会一起改变,,
3、如果两者都实例化,肯定是两个不同的对象,内存地址不可能共用的,就算是Dog实例化多次也是只是多个不同的对象,内存地址是不一样的,,
4、super其实就是一个区分标志,不会新建对象的,,,super()只是调用父类的无参构造方法,因为子类也有无参构造方法,,只要是子类要调用在父类中有同名同参的方法或者同名的属性,都要用到super来区分,,
关于这部分的资料感觉还是蛮少的,所以这个想法是否正确也不能保证。
还有一个很有意思的东西
package cn.sxt.oop;
public class A {
int i = 12;
}
class B extends A {
int i = -6;
public static void main(String[] args) {
A xx = new B();
System.out.println(xx.i);
}
}
/**
result:
12
**/
B实例的i值是A类的i值,有点懵
关于java子类继承来的属性与方法究竟是完全复制还是共用使用相关教程