如果一个类A代码如下:特别注意age是私有的。
package test;public class A {
    private int age;
    public A() {
     System.out.println("调用A的构造方法");
    }
    public int getAge(){
     return age;
    }
    public void setAge(int age){
     this.age=age;
    }
}
有一个子类B继承了A类:
package test;public class B extends A{
    public B() {
     System.out.println("调用B的构造方法");
    }  
    public static void main(String[] ss){
     B b=new B();
        //b.age=34;//没有继承,不能直接赋值
     b.setAge(34);
     System.out.println("b.age= "+b.getAge());
    }    
}输出结果是:
调用A的构造方法
调用B的构造方法
b.age= 34显然B不能继承父类的私有变量age,但是可以继承A类的getter/setter方法,当调用b的set方法给age赋值时,这个值“34”到底是赋给谁了?是A类的age么?如果是的话,似乎是当创建子类对象b时,也同时创建了A类的对象,(输出结果显示,在调用B类的构造方法时,也事先调用了A类的构造方法。)那么如果是在创建子类对象时父类对象也同时被创建了,那么、一个大的系统中要有多少个Object对象啊!
从另一个角度来看这个问题:如果A类是个抽象类,理论上抽象类是不能被实例化的,代码如下:
package test;public abstract class A {
private int age;

    public A() {
     System.out.println("调用A的构造方法");
    }
    public abstract void test();
    public int getAge(){
     return age;
    }
    public void setAge(int age){
     this.age=age;
    }
}B类代码:
package test;public class B extends A{    public B() {
     System.out.println("调用B的构造方法");
    }
    public void test(){
     System.out.println("实现的抽象方法test()");
    }
    public static void main(String[] ss){
     B b=new B();
     //A a=new A(); 不能被实例化
     b.setAge(34);
     System.out.println("b.age= "+b.getAge());
    }    
}
运行结果依然如故,谁能解释一下,这中间到底age从哪来,其中应该是怎样的过程。

解决方案 »

  1.   

    1 父类也创建了2 抽象类也是类,也会被编译成.class文件,加载到内存中
      

  2.   


    你自己调试下就明白了!
    父类A中有age这个属性,B继承A后,当然也就有age这个属性了!
    如果在B类中没重新设置这个age属性
    在 b.setAge(34); 的时候,
    会进到A中的 public void setAge(int age){ 
        this.age=age; 
        } 
    setter方法设置age的值!
    当你在B中重新设置了age属性,则就会调用自己类中的setter方法!
    既然继承了A,当然就可以不用重复写雷同的代码,不然不就冗余了!public class A{
    private int age; 
        public A() { 
        System.out.println("调用A的构造方法"); 
        } 
        public int getAge(){ 
        return age; 
        } 
        public void setAge(int age){ 
        this.age=age; 
        } 
    }public class B extends A{
    public B() { 
        System.out.println("调用B的构造方法"); 
        }  
        public static void main(String[] ss){ 
        B b=new B(); 
            //b.age=34;//没有继承,不能直接赋值 
        b.setAge(34); 
        System.out.println("b.age= "+b.getAge()); 
        }  
        
        private int age; 
        public int getAge(){ 
        return age; 
        } 
        public void setAge(int age){ 
        this.age=age; 
        } }你自己去调试下,就会明白上面我说的,赋值的时候,会从哪进去。你自己去调试就明白了!
      

  3.   

    A中age是私有的属性!但是我们可以通过公有的访问器getter和setter方法去读写!
      

  4.   

    即使是在b类中设置了age属性,当调用setAge()方法时仍然会调用A类的setAge()方法。不能调用B类的setAge()方法。代码如下:
    package test;public class B extends A{
    private int age;
        public B() {
         System.out.println("调用B的构造方法");
        }
        public void test(){
         System.out.println("实现的抽象方法test()"+super.getAge()+" : "+this.age);
        }
        
        public static void main(String[] ss){
         B b=new B();
         //A a=new A();
         b.setAge(34);
         b.test();
         System.out.println("b.age= "+b.getAge());
        }
        
    }输出结果是:调用A的构造方法
    调用B的构造方法
    实现的抽象方法test()34 : 0
    b.age= 34显然B类自己的age没有被赋值,除非覆盖了A类的setAge方法,B类的age才会被赋值。这样的话,子类继承的方法,还不能算是真正是自己的,还是父类的。
      

  5.   

    给你个初始化顺序吧,java编译器确保域(成员变量或块)在被使用之前必需初始化,即使你没直接初始化,它也会默认给你一个值。 1. 
      如果不涉及继承跟static,用new创建对象时,会调用那个类的构造函数,而在调用构造函数之前必需先初始化域(因为在构造函数里,可能会用到这些成员变量) 
    等域初始化完后再调用构造函数。强调一点:只要是成员变量,那么不管它放在类的哪个部位(但在方法或块内部不算,因为那算是局部变量),它都在构造函数调用之前调用,这是编译器确保的。 2. 
    如果涉及继承,当用new创建子类对象时,调用顺序是这样的: 
      1.先初始化父类的域(成员变量或块) 
      2.调用父类的构造函数(没有明确定义的话,调用默认那个,即编译器为你创建的) 
      3.再到子类,初始化子类的域 
      4.这时才轮到调用子类的构造函数 
    原则是:要确保域在被调用之前要被初始化. 
    上面是涉及两层,如果是涉及多层继承的,那么一致递推上去,即先初始化父类的域,然后调用父类构造函数,再初始化子类的域然后再调用子类的构造函数,再初始化子子类的域(用这个名字好像有点怪,哈哈,就是孙子类的意思)然后再调用子子类的构造函数,一致类推下去 
    3.涉及static的话,static域是在编译的时候加载的,原则是: 
      1.static域是在非static(上面说的都是非static)之前调用的 
      2.static域只初始化一次(即只调用一次),打个比方A a = new A(); A 里有static域,只有当你第一次使用new创建对象的时候它会在非static之前调用,而如果你还想再用new创建对象时,static域这段代码是不会被调用的(因为static的东西是属于类,所以对象共享的,一次就够了) 4.如果涉及继承跟static结合的话(而这个是初始化里最难的,很多初学者会卡在这里),只要按照3.2结合就行了。 
      

  6.   

    A中的age可以通过共有变量间接访问