最近我们公司招人,看了下笔试题,有道题不理解
题目如下
class SuperClass{
private int number;
public SuperClass(){
this.number=0;
}
public SuperClass(int number){
this.number=number;
}
public int getNumber(){
number++;
return number;
}
}class SubClass1 extends SuperClass{
public SubClass1(int number){
super(number);
}

}
class SubClass2 extends SuperClass{
private int number;
public SubClass2(int number){
super(number);
}

}
public class SubClass extends SuperClass{

private int number;
public SubClass(int number){
super(number);
}
public int getNumber(){
number++;
return number;
}

public static void main(String[] args) {
SuperClass s=new SubClass(20 );
SuperClass s1=new SubClass1(20 );
SuperClass s2=new SubClass2(20 );
System.out.println(s.getNumber());
System.out.println(s1.getNumber());
System.out.println(s2.getNumber());
}}
执行结果是
1
21
21

请问:s.getNumber() 结果为什么是 1啊?!!

解决方案 »

  1.   

    因为subclass构造函数中的number是赋值给superclass的
    subclass本身变量number值并没有改变 还是初始值0;
      

  2.   

    继承过程中 只能继承公共变量 private 所修饰的变量是不能继承的 所以subclass中的number 还是自己的 而不是父类的 s.getNumber()调用自身的方法 -->自身的number++ 自身的number初值是0 所以最后结果是1
      

  3.   

    SubClass2也是private int number;
    为什么得出的结果是21????
      

  4.   

    3楼的说的对!
    SubClass2也是private int number;但是它在构造方法里调用了super(number);所以和它自己的number没关系的。可以在SubClass2的构造方法用this.number来打印看看,这个值是0。
      

  5.   


    public class SubClass extends SuperClass{private int number;
    public SubClass(int number){
    super(number);
    }
    public int getNumber(){
    number++;
    return number;
    }此代码中当new SubClass(20)的时候,调用构造函数public SubClass(int number)方法,super(number)中的number变量是指的public SubClass(int number)中的number,它是一个局部变量,作用域只限于构造函数。而SubClass类的成员变量private int number初始化为0,所以执行number++以后就变为了1.这应该是考变量作用域以及继承方面的知识。
      

  6.   

    我看了半天,同意7楼的,super(number)这句话改变的是superClass中的number值。在SubClass1,SubClass2没有重写getNumber()方法,所以输出的是superClass中的number,因为在SubClass中重写了getNumber()方法,所以在SnbClass中输出本身的number,因为初始值为0,所以输出为1
      

  7.   

    SubClass的构造函数只对父类的number赋值,SubClass的number属性未赋值是默认的,调用getNumber时调用的是子类覆写的方法,子类覆写的方法调用的number是子类的值,固为1
      

  8.   

    主要是subclass重写了 父类的getnum方法
      

  9.   

    int number是私有变量,子类不能继承,所以调用super(20)时,被赋值的是父类里面的number,子类里面的number并没有被赋值。在SubClass类中覆盖了父类的getNumber(),返回的是当前子类的number,但在对象声明时并没有被赋值,因此返回的是number初始值+1;而SubClass1和SubClass2继承了父类的getNumber(),返回的也是父类的number,在对象声明时已经被赋值。
    综上所述,得出的结论就是s.getNumber()==1;s1.getNumber()==21;s2.getNumber()==21 。
      

  10.   


    不急,慢慢来,打开netbeans,把代码放进去,然后格式化代码,并且根据提示加上@Override,然后看到一般情况下大家喜欢的格式:/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package mytester;/**
     *
     * @author Rains.C
     */
    public class Main {  /**
       * @param args the command line arguments
       */
      public static void main(String[] args) {
        // TODO code application logic here
        SuperClass s = new SubClass(20);
        SuperClass s1 = new SubClass1(20);
        SuperClass s2 = new SubClass2(20);
        System.out.println(s.getNumber());
        System.out.println(s1.getNumber());
        System.out.println(s2.getNumber());
      }
    }class SuperClass {  private int number;  public SuperClass() {
        this.number = 0;
      }  public SuperClass(int number) {
        this.number = number;
      }  public int getNumber() {
        number++;
        return number;
      }
    }class SubClass1 extends SuperClass {  public SubClass1(int number) {
        super(number);
      }
    }class SubClass2 extends SuperClass {  private int number;  public SubClass2(int number) {
        super(number);
      }
    }class SubClass extends SuperClass {  private int number;  public SubClass(int number) {
        super(number);
      }  @Override
      public int getNumber() {
        number++;
        return number;
      }
    }
    在第21,22,23,24行打上断点符号,然后“调试”主项目:
    运行第21行之前,结果是(netbeans显示):
    s有自己的number = 0, 继承的number = 20
    s1只有继承的number = 20
    s2有自己的number = 0, 继承的number = 20然后“继续”(运行第22行之前)
    结果是:
    s自己的number = 1, 继承的number = 20
    其他不变然后继续:(运行第23行之前)
    s不变
    s1继承的number = 21
    其他不变然后继续(运行第24行之前):
    s和s1不变
    s2自己的number = 0, 继承的number = 21调试结束。整个过秤的变量中间结果如此,现在反过来推敲是什么步骤导致这样的中间结果。首先变化的是s自己的number,继承的number不变。
    这个动作由21行的s.getNumber()引起,
    观察s的定义:s是鸡肋(基类),用子类填充(实例化),
    子类实例化的具体步骤是super(number),即调用鸡肋的构造器。
    鸡肋的构造器对鸡肋自己的number赋值,这个很好理解。
    如果我没有看错的话(现在是凌晨2点30,我希望我没看走眼),3个子类的构造器通通是调用鸡肋的,
    观察“调试”模式的变量中间结果,可以很轻易的得到结论:number域可以被继承。
    因此,第21行执行前,S,S1,S2三个对象的继承来的number域都是20,这个由18,19,20行的实例化方式及参数看得出。回到s.getNumber()方法,这个方法返回的是子类 -自己- 的number域, 系统为这个未初始化的域赋予默认值0,那么get以后得到1,很好理解。继续,s1.getNumber()方法:s1没有定义这个方法,系统找s1的鸡肋的public的getNumber方法,找到了!之行……结果是s1的继承来的number域变成21,嗯,正如所料。继续,s2.getNumber()方法:和s1没区别;
    另一个证据是:在netbeans里面,SubClass2的number域下面有波浪线,系统提示:“未使用字段”

    我模仿处女座举证的方式,罗列了netbeans中的事实,供大家思考。有一些建议如下:
    1、建议非对象的私有域最好给个初值,比如int = 0;
    如果私有域是对象,最好给个Null,反而不要赋值,避免递归定义,堆栈溢出,比如:public class A {
      private A a = null;
      //private A a = new A();
    }
    很难说你的构造器里面有if(A != null) return;2、域放在方法后面,除非写算法。3、继承和接口,首先考虑接口。4、尽量不用默认的访问控制,把域标记为private而不是空着,然后提供访问器和设置器。    ——from 《Effective Java》
      

  11.   

    SuperClass s1=new SubClass1(20 );
    创建s1对象时,调用的是父类的带参数的构造方法,于是父类number=20;因为子类SubClass1没有重写父类的getNumber()的方法,只能从父类继承,所以getNumber()所取得的值是父类的number+1;
      

  12.   

    主要还是 subclass 重写了 getNumber 方法
    又因为 subclass 的变量时私有的
    导致subclass的值为1
    而subclass2没有重写getNumber方法
    subclass2又继承了superclass
    导致getNumber方法返回的是21
      

  13.   

    很简单的识别方法:
    SuperClass s = new SubClass(20);  //根据new SubClass(20); 20是进入SubClass的构造方法。
    SuperClass s1 = new SubClass1(20);
    SuperClass s2 = new SubClass2(20);
    System.out.println(s.getNumber());//根据第一行SuperClass s;getNumber()是进入SuperClass的方法。
    System.out.println(s1.getNumber());
    System.out.println(s2.getNumber());
      

  14.   

    错了//根据第一行SuperClass s = new SubClass(20); ;getNumber()是进入SubClass的方法。
      

  15.   

    SuperClass s = new SubClass(20);  子类重写了getNumber()方法!实现了多态!并且父类的number是private是不能继承的!只能用自己的!而自己的初始值是0 所以 getNumber()后是1;下面两个很容易理解!
      

  16.   

    考的是getNumber()方法在subClass里面的override
      

  17.   

    开始时继承父类的方法,本身的初值this.number=0,但是在方法的执行时number++
    ,所以结果就是1
      

  18.   

    继承过程中 只能继承公共变量 private 所修饰的变量是不能继承的 所以subclass中的number 还是自己的 而不是父类的 s.getNumber()调用自身的方法 -->自身的number++ 自身的number初值是0 所以最后结果是1
      

  19.   

    这是多态性,覆盖,子类覆盖了父类的getNumber(),调用是会检查,如果子类有自己的getNumber()方法则执行子类的,没有就执行父类的
      

  20.   

    多态了,subclass对象的引用给了superclass,调用的是subclass的getNumebr,subclass的getnumber操作的是自己的number变量,构造器赋予的number变量给父类了。
      

  21.   

    错 错  错  私有的变量可以继承不然 子类的调用父类的get 私有变量的方法怎么可以  可以继承不能直接访问 。。
      

  22.   

    s2.getNumber()是调用superClass的方法。
      

  23.   

    这个没有什么绕的,你们没有理解透java机制,我换种写法你们就不难理解了。
    class SubClass1 extends SuperClass{
    public SubClass1(int number){
    super.number=number;
    }
    //getNumber方法没有被继承,多态时使用父类方法
    }
    class SubClass2 extends SuperClass{
    private int number;
    public SubClass2(int number){
    super.number=number;
    }
    //getNumber方法没有被继承,多态时使用父类方法
    }
    public class SubClass extends SuperClass{private int number;
    public SubClass(int number){
    super.number=number;
    }
    public int getNumber(){
    this.number++;
    return this.number;
    }
      

  24.   

    java参数传递分为值传递和址传递,这种属于值传递,只是复制数据而已
      

  25.   

    做好测试,也要学好开发。
    我的微薄:http://t.sina.com.cn/teststar