class S1{
    String s="S1";
    void a(){
        System.out.println(s);
    }
}
class S2 extends S1{
    String s="S2";
}
public class Example {
    String s="Outer";
    public static void main(String[] args) {
        S2 s2=new S2();
        s2.a();
    }

这段代码为什么结果是S1啊?

解决方案 »

  1.   

    动态绑定的问题。运行a()时绑定的s="S1"。
      

  2.   

    S2继承了S1,不就是说S2中也有a()方法啊,和动态邦定有关系么?
      

  3.   

    如果你把写成
    class S2 extends S1{
        String s="S2";
         void a(){
            System.out.println(s);
        }   
    }那么结果就是“S2”了,可能是因为s2中有a()这个方法,所以运行a()的时候结果是“s2”
    当s2没有a()方法是,就向父类找这个方法,当找到之后就直接运行父类的a(),当然这个
    a()也理所当然的用自己,也就是父类中的s了`
      

  4.   

    就我粗略的理解
    laolaocao(加勒比强盗)给的方法是正确的
    但是解释似乎不太准确复写的应该是方法(method)
    而不会是变量
    你在class S2中“复写”变量s是不成功的
    实际上你得到了另一个变量而laolaocao(加勒比强盗)的 class S2 复写了 method a()
    如果写成这样
    class S2 extends S1{
        String s="S2";
         void a(){
            System.out.println(super.s);
        }   
    }
    结果会还是"S1"
    原因我想你现在应该明白了
      

  5.   

    S2也继承了S1的属性s啊,s的可见性也是包可见性,那么在S2中应该是重新给属性s付了一个新值吧?
      

  6.   

    我不是大猩猩 但是在另一个地方有一样的问题
    http://www.cjsdn.net/post/view?bid=1&id=26573&tpg=1&ppg=1&sty=1&age=0#26573可能是JAVA的规则.同名覆盖上,在子类对象中函数上父类对子类隐藏,
    变量上子类对父类隐藏.不知道这样的理解是否正确。还望老手指教~
      

  7.   

    父类子类各有一个s
    各自的Constructor设置各自的s输出时,没有override,就不是动态联编,
    s2被声明为什么类型,那就输出那个类型的s一楼的老兄说的是对的。望高手能讲根本质的原理~
      

  8.   

    自己顶一下有一个资料上是这么解答的:
    子类S2中未定义a()方法,因此在子类S2实例s2上调用的a()方法是继承自复类S1中的,
    由于a()方法只能对同类上的类成员变量s进行访问,因此输出S1
      

  9.   

    子类S2中未重载a()方法,所以会调用父类中的方法,而父类中的方法又不会调用它类中的变量,所以输出的结果是S1
      

  10.   

    我试着解答一下:
    这里面涉及到两个JAVA的核心问题,第一个是继承的问题,先来看<Thinking in java>里面的一段话:
    But inheritance doesn’t just copy the interface of the base class. When you create an object of the derived class, it contains within it a subobject of the base class. This subobject is the same as if you had created an object of the base class by itself. It’s just that, from the outside, the subobject of the base class is wrapped within the derived-class object.
    翻译成中文大致是说导出类(子类)不仅仅是继承基类(父类)的接口,而且在创建导出类对象的时候,它会包含一个基类的子对象, 这个子对象和从基类直接创建出来的子对象没有任何不同.只是从外面看起来, 这个子对象被导出类对象包裹在里面了.
    第二个问题是继承是否会覆盖同名成员的问题, 答案是JAVA中不会覆盖任何的同名成员.
    说到这里,答案基本上就出来了, S2中没有a()方法,用的是内置基类S1的a()方法, 而a()方法访问的是S1的成员s, 结果为"S1".
      

  11.   

    laolaocao(加勒比强盗)和tianshul8(闲耘) 说的基本上是正确的, 只是没有从原理上解释一下.
    但有一点也需要更正, 就是JAVA中除了不会复写成员变量, 也不会复写成员方法, 这一点和C++是不同的.
      

  12.   

    简单的说就是     
    void a(){
            System.out.println(s);
        }这里的s取的只能是S1里的s,因为你并没有把S2的对象传进来
      

  13.   

    我的理解是,S2的对象有两个成员变量,一个从S1里继承过来,一个是自己的,名字都叫s,从下面的例子可以证明:class A {
    public String a = "abc";
    }class B extends A {
    public String a = "def";
    public void a() {
    System.out.println(this.a);
    System.out.println(super.a);
    }
    }S2的对象没有a方法,所以,调用父类(S1)的a方法,S1类使用S1.s变量。