class Base 
{ protected int a; 
  Base() { 
    a = 1; 
  } 
} class Child1 extends Base 

Child1(){ 
  a = 2; 
  System.out.println(a); 

public int getBaseA() { 
  return super.a; 

} class Child2 extends Base 

  Child2() { 
  a = 3; 
  System.out.println(a); 
  }   public int getBaseA() { 
  return super.a; 
  } 
} public class  Test 

  public static void main(String[] args) 

  Child1 ch1 = new Child1();  
  Child2 ch2 = new Child2();  
  System.out.println(ch2.getBaseA());          // child1与child2有同1个父类,这里的 super.a 为3, 
  System.out.println(ch1.getBaseA());          // 而为什么这里的 super.a 又为 2 ? 
  } 
} 输出结果为 2,3,3,2 哪位能解释清楚为什么输出结果如此即可,谢谢 ? 我主要困惑在于继承之后,子类究竟是在自己的内存中新建1个变量a 还是包含1个指向父类的指针,从这程序来看,貌似两种情况都不是. 

解决方案 »

  1.   

    是父类的引用指向子类的对象child1 child2 已经继承了Base
    那么就继承了他的非私有的成员
      

  2.   

    protected 是受保护的,不能被继承~就这么简单
      

  3.   

      我记得哪本书里有看到是同1个地址,子类里有1个指针指向父类对象。刚才那个之所以一个3,一个2,是因为new 2个子类,2个子类的父类是不同的一个父类对象。不知道是不是这个答案?
      

  4.   

    Child1 ch1 = new Child1();  在构造器中打印了a=2,这个a是ch1的a;
    Child2 ch2 = new Child2();  在构造器中打印了a=3,这个a是ch2的a;
    System.out.println(ch2.getBaseA());打印ch2中的a=3;
    System.out.println(ch1.getBaseA());打印ch1中的a=2;
    子类是在自己的内存中新建1个变量a。子类new时,是先调父类的构造器的。也就是说父类也new了。
      

  5.   

    ch1和ch2中的a实际上是分别指向两个不同地址的父类对象中的a变量的。
      

  6.   

    4楼说得是好的.但是
    不苟同红色部分的.在初始化时,是先进行父类初始化再进行子类的.所以当然是先让a = 1,进而再进行赋值为2或赋值为3的操作(这也就是最后再输出3,2的原因).会调用父类的构造函数,但是不是new一个父类.调用父类的构造函数只是为初始化工作服务的,因为子类有从父类那里继承来的属性,这些属性通过父类的构造函数进行初始赋值.
    至始至终,都没有父类被构建.super调用的可以说只是调用了存储在子类里面的父类属性,而这些信息说到底还是子类的.简单地说:不能说你继承自你父亲高挺的鼻子就断定你的鼻子就是你父亲的了.
      

  7.   

    父类new的话 父类的对象数据放到那里?
    子类new的话,子类的对象数据放到那里?
    new子类的时候,可仅仅是有一个指针啊。
    大侠们回答下。
      

  8.   

    protected 指定该变量可以被同一个包中的类或其子类访问,但是不能通过超类的实例来实现,在子类中可以覆盖此变量!
      

  9.   

    那super()算不算一个超类的实例????
      

  10.   

    这是可能对继承的概念本身有一点儿混淆了,用C结构来解释的话
    你可以想象成这样的内存布局, Child1和Child2没有自己再定义变量,
    所以继承了Base的a成员变量,Protected只是告诉编译器,我希望可以在
    Child1和Child2内也可以修改这个变量,当你生成Child1,Child2的实例时,
    它们存在于各自的内存块内,各自独立变化,当然不会相互影响了。struct Base

       int a;
    }struct Child1 

       int a;
    }struct Child2 

       int a;
    }
      

  11.   

    int i;
    public A(){
       i=1;
    }
    public A(int i){
       this();
       this.i=i;
    }
    这里的this()也算new 了一个实例?内存里有空间吗?
    那我再new A(5) 算是new了一个实例吧,那this()的实例放到那里去了?new A(5)的空间呢,放到那里去了?
      

  12.   

    构造函数上面你如果int i=0;属性可以只声明,也可以声明初始化一起做,例如int i=0;构造的时候我也可以改变的它的值啊。我也可以什么都不做,我想构造器是这样工作的,先看一下自己的属性是只被声明没有初始化,构造器可以初始化它,也可以不初始化,默认是0嘛!
      

  13.   

    应该是整个过程没有实例化父类,而只是在调用子类构造函数之前先调用父类的构造函数将a=1,这是的a应该是在子类中的内存的一个变量,然后在执行完父类的构造函数后再执行子类的构造函数时,子类的a被重新赋值了。所以就分别得到2,3了。拙见。
      

  14.   

    在加一个,输出多少?
    Base ch3 = new Child2();
    System.out.println(ch3.getBaseA());
      

  15.   

      我觉得创建子类对象的时候,同时也创建了1个父类对象,因为我在看开源项目"Jive论坛"的时候,里面有计算对象缓存的大小,每个对象的大小都要加上1个Object,说明同时也创建了1个Object对象,并不只是调用Object的构造器,我是这么理解的,不知对否 ?
      

  16.   

    关于继承:创建子类对象时,首先创建一个父类对象,并把父类对象作为子类对象的一部分。关于楼主的疑惑,子类对象和父类对象他们用的是同一个变量(在内存中也是),甚至是同一个引用!!这就不难理解你这道题的输出结果了:在Child1和Child2他们构造方法中已经对Base中a的值(其实也是两个子类中的a)进行了赋值,也就是说已经把内存中存储的值变成了2和3,所以无论你在构造方法中输出还是在test中调用getBaseA()和getBaseB()输出的都是2和3。
      

  17.   

    呵呵。。那是不是就是一个protect的变量受保护不能被继承,引起的呢?
      

  18.   

    哦。。就是说如果在继承父类的时候,new 一个新的变量或者其他,跟父类的变量一样的话就会比覆盖,就是8楼说的子类的变量由此覆盖父类的变量一样
    是吗、
      

  19.   

    你的子类有和父类同名字的属性吗,也就是你的子类中也定义了a了吗!只有定义了super.a和a才有区别,如果子类中没有定义的话,那么super.a和a都指向父类那个a了!!
      

  20.   

    public class  Test 

      public static void main(String[] args) 

      Child1 ch1 = new Child1();  //ch1实例化的时候先调用了super.(),然后给变量a赋值为2,所以最后一句打印2
      Child2 ch2 = new Child2();  //ch2实例化的时候先调用了super.(),然后给变量a赋值为3,所以下一句打印3
      System.out.println(ch2.getBaseA());          // child1与child2有同1个父类,这里的 super.a 为3, 
      System.out.println(ch1.getBaseA());          // 而为什么这里的 super.a 又为 2 ? 
      } 

      

  21.   

    这里好的做法是:定义类的属性时尽量采用private,而设置公有set,get方法。子类继承时只需要继承方法,不好直接继承父类属性。
    34楼说的好。
      

  22.   

    在内存中heap 这里new 出来的对象都是各自是各自的的  其参数的变化也是自己对象内部进行变化的这里就和声明成员变量等常量不一样了  
    如果要很深入的话  就是  heap,stack,codedegment,constant pool了!!!!!
    建议你感觉程序可以看懂的话,,,,就可以看看内存分析了   看了以后 你会感觉柳暗花明的!~~~~~~~~~~~
    我就是那样过来的
      

  23.   

    是这样的。两个方面回答你的问题:
    首先在构造子类函数时,同时也构造了父类函数,即
    Child1(){ 
      super();
      a = 2; 
      System.out.println(a); 

    所以你若问子类是在自己的内存中新建1个变量a ?当然是,只不过是在构造父类时创建变量a的。其次child2在构造函数时,也构造了父类函数。
     Child2() { 
      super();
      a = 3; 
      System.out.println(a); 
      } 
    两个super()都是new父类,即各自给父类分配了不同的地址,因此,两个子类的父类是毫无瓜葛的。
      

  24.   

    你说都是 new父类,那如果父类是抽象类呢 ?
      

  25.   

    经过验证,父类为抽象类的话,new子类的时候,父类的构造器也可以调用。
    abstract class abs {
    int i=0;
    public abs(){}
        public abs(int i){
       this.i=i;
       }
        public int geTI(){
        
         return i;
        }
        public abstract String getI();
        
    }
    public class abc extends abs{
    public abc(int i){
    super(i);
    }
    public String getI(){
    return "nihao" ;
    }
    public static void main(String[] args){
        abs abc=new abc(5);
        System.out.println(abc.geTI());
    System.out.println(abc.getI());
    }
    }
      

  26.   

    我也想插两句嘴,我觉得这个问题本来是很简单的,为什么会有这么多种解释:首先,继承关系,指的是子类继承了父类。继承的是父类中的方法和域(也叫属性)。那么,super.a和this.a指的就是同一个对象。只要a没有声明成静态域,那么,变量a就只对对象有意义,它们所对应的内存地址肯定就不一样了。所以,不存在楼主所说的子类会在内存中新建一个变量a,同时,也没有一个指向父类的指针。(a不是静态变量,父类或者说强调类,并没有一个新建一个变量。而只能说对象ch1和对象ch2有两个变量,ch1.a,ch2.a。在对象ch1中,不管你使用super.a还是this.a,指向的都是ch1.a,ch2也是同样的道理。弄清楚了这一点,那么这个程序执行的过程,相信也不需要多说了。
      

  27.   

      只要成员变量不是static的,每次实例化一个子类的对象,实际上都包含了一个父类的对象,抽象的父类虽然不能去new,并不表示子类就不能拥有其对象了,并且每个子类的这个父类对象里的成员都是各不相同的.  如果成员声明为static的估计就能得到想要的结果了:  2,3,3,3
      

  28.   

    Child1 ch1 = new Child1();  创建对象ch1,构造父类1
    Child2 ch2 = new Child2();  创建对象ch2,构造父类2ch1在创建时通过:Child1(){ a = 2; };   把父类1的a变为2;
    ch2在创建时通过:Child2(){ a = 3; };   把父类2的a变为3;Child1 ch1 = new Child1();  输出父类1的a:2
    Child2 ch2 = new Child2();  输出父类2的a:3
    System.out.println(ch2.getBaseA()); 输出父类2的a:3
    System.out.println(ch1.getBaseA()); 输出父类1的a:2对象ch1和ch2共用同一个父类,那是在定义的时候。
    但创建对象时,对象ch1和ch2都有自己的“父对象”(不知道这样说对不对,先这样叫吧),两个不同的对象!所以结果如此。