class s1
{
public String s="s1";
public String get()
{
return s;
}
}
class s2 extends s1
{
public String s="s2";
public String get()
{
return s;
}
}public class s
{
public static void main(String[] args)
{
s1  a = new s2();
System.out.println(a.s);
System.out.println(a.get()); 
}
}高手帮忙啊,谢谢.

解决方案 »

  1.   

    s1
    s2
    get()方法被覆写,动态地调用,而s2类中包含两个成员变量名称均为s,但是如:s2 a=new s2();System.out.println(a.s)只能输出s2,就好比被屏蔽了,要调用在s2的实例中访问子类的变量只能上溯为s1,然后调用s1的变量s
      

  2.   

    谢谢各位!谢谢superslash(开始用功学习) 
    我比较笨,对你那句"要调用在s2的实例中访问子类的变量只能上溯为s1"不太理解,可否讲得通俗点,谢谢.
      

  3.   

    我的意思是你如果想通过s2的实例而访问父类s1的变量s是不可以的,必须通过向上转型为s1才可获得:s1  a = new s2();//此句向上upcast
          System.out.println(a.s);//可以访问s1中的s,输出s1
    如果这样
           s2 a=new s2();
           System.out.println(a.s);//输出的乃是s2,虽然a中的确存在一个字符串,它的值为"s1",但是你却不可能访问到它,所以尽量不要让子类的成员变量名等同于父类的
      

  4.   

    这个地方就是多态的一个陷阱;
    多态是对方法而言的,不是对变量;
    s1 a = new s2();这里生成的对象是s1类的实例,但是是由s2类构造的;java中对变量的选择是静态的,对方法的选择是动态的,是在运行时决定的。(static除外)
    运行时实际上调用的是实例的方法,即s1的方法;但对于继承(多态的一种方式),方法的定位是在动态执行时选择的,选择实际构造者,因此就出现了本题的现象了。
      

  5.   

    crazycy(代言人) 
    对变量的选择是静态的,对方法的选择是动态的---------------------------
    楼主,你要的答案
      

  6.   

    受教了 说一点想法:
    s1 a = new s2();需要注意的是,a是s1实例,不是s2的,后面的s2是类s2的构造器。
    关于变量,是哪个类的实例,就调用哪个类的成员变量;
    关于方法,使用了子类的构造器,如果子类重写了父类的方法,就调用子类的;子类没有该方法,则调用父类的。
      

  7.   

    class s1
    {
    public String s="s1";
    public static String s0="s1";
    public String get()
    {
    return s;
    }
    public static String get2()
    {
    return s0;
    }
    }
    class s2 extends s1
    {
    public String s="s2";
    public static String s0="s2";
    public String get()
    {
    return s;
    }
    public static String get2()
    {
    return s0;
    }}public class s
    {
    public static void main(String[] args)
    {
    s1  a = new s2();
    System.out.println(a.s);
    System.out.println(a.get());
    System.out.println("*****************************************");
    System.out.println(a.s0);      //---------------021
    System.out.println(a.get2());  //----------------022
    System.out.println("*****************************************");
    System.out.println(s1.s0);     //----------------031
    System.out.println(s1.get2());  //------------------032
    System.out.println("*****************************************");
    System.out.println(s2.s0);    //--------------041
    System.out.println(s2.get2());  //----------------042
    }
    }这个也比较有趣。
    021,031,032,041,042的结果大家应该都能看出来,不过022的结果可是需要好好考虑一下。
    022打出的结果是s1
    我想这应该和分配内存的时间不同有关。静态变量和方法是在类加载的时候分配内存的,而成员变量和方法是在调用的时候分配内存的。所以当声明s1 a的时候,虚拟机已经给s2分配了内存,所以022打得是s1.给人看法,不对的话 请方家指点 。B-)
      

  8.   


    crazycy(代言人)
    对变量的选择是静态的,对方法的选择是动态的
    ===============
    有些不严密,方法应该有个修饰,就是除了final修饰的方法外,java中对函数的调用都是后期绑定,所谓的后期绑定就是动态选择