public class Base{
public static final String FOO = "foo";
public static void main(String []arg){
Base b = new Base();
Sub s = new Sub();
System.out.println(Base.FOO);
System.out.println(Sub.FOO);
System.out.println(b.FOO);
System.out.println(s.FOO);
System.out.println(((Base)s).FOO);//A处 System.out.println("(Base)s  :  getClassName = " + ((Base)s).getClass().getName());//此处输出为Sub,为何A处输出却不是Sub.Foo 的值bar,而是foo呢?? }
}class Sub extends Base{
public static final String FOO = "bar";
}

解决方案 »

  1.   

    一般程序不会这样去设计,既然是静态常量,子类中就不应该去重新申明(虽然java可以支持),对于静态对象的调用是根据类去调用的,所有A处输出的是foo,而getClass方法是非静态方法,是根据对象调用的,不管怎么进行转换最终输出的都是sub。
      

  2.   

    楼主的问题所涉及的知识点:向上转型跟RTTI(运行时类型信息)
    首先对于A处,s向上转型为父类型,再调用FOO,如果此时父类有变量FOO则就执行父类的,如果父类没有再执行子类的,这个没话说。
    再看第二处,这个涉及到RTTI(运行时类型信息): 
        在java里,类型信息在运行时是如何表示的呢?是通过被称为Class对象的特殊对象来完成的,它包含了类有关的信息,每一个类都有一个Class对象
    换言之,每当编写并且编译一个新类时就会产生一个Class对象(保存在同名的.class文件中),而调用一个对象的getClass()方法实际上把保存在对象中
    的记录本类信息的特殊对象Class对象拿出来,而这当然就是只本来产生对象的那个类了。 建议楼主再看看关于java运行时类型信息方面的知识.
      

  3.   

    System.out.println (((Object)new String("")).getClass().getName());
    以上代码运行后,输出java.lang.String
    很明显我们可以看出,getClass()方法是由对象调用
    并返回这个对象所在最小范围内的类名
    所以((Base)s).getClass().getName())是Sub((Base)s).FOO
    很明显,static字段由类来调用,而父类中有FOO这个字段,
    所以是foo
      

  4.   

    (Base)s这里是子类的对象指向父类的引用,输出FOO时是调用的父类的FOO,这是java中的upcasting,多态的体现,但它依然是子类的对象啊,所以调用getClass().getName时还是输出的Sub
      

  5.   


    你这话怎么都是说反的呢
    应该是父类的引用指向子类的对象,这是upcasting,但这哪里是多态的体现?
    成员变量,静态变量都没有多态这个概念,是谁的引用就调谁的
    静态变量的调用就像楼上某位同志说的,跟class相关,跟具体的instance没有关系,而且通常也不建议instance.staticVal这样的调用方式至于那个getClass方法才是多态的
      

  6.   

    觉得还是在(Base)s上找问题,强制类型转换器是并不是把s指向的子类对象转化成父类对象了
    而是将s这个指向子类的引用转换成了指向父类的引用,2楼的这句话我不太认同:首先对于A处,s向上转型为父类型,再调用FOO,如果此时父类有变量FOO则就执行父类的,如果父类没有再执行子类的,这个没话说。
    如果父类没有,显然也不会执行子类的,编译就不会通过,这就是向上转型的时候丢失类型的结果,(Base)s的结果是s仍然指向着子类对象,但是调用时会执行
    父类的代码。
    接着(Base)s调用 getClass();getClass()是Object的方法
    public final Class<? extends Object> getClass()返回一个对象的运行时类。该 Class 对象是由所表示类的 static synchronized 方法锁定的对象。 
    红字所写我的理解就是该class对象是不可以更改的
    返回:
    表示该对象的运行时类的 java.lang.Class 对象。
    Class 类的实例表示正在运行的 Java 应用程序中的类和接口
    显然s指向的是一个sub的对象调用getClass()返回sub也就合理
      

  7.   

    一般程序不会这样去设计,既然是静态常量,子类中就不应该去重新申明(虽然java可以支持),对于静态对象的调用是根据类去调用的,所有A处输出的是foo,而getClass方法是非静态方法,是根据对象调用的,不管怎么进行转换最终输出的都是sub。
      

  8.   

    1,对于System.out.println (((Object)new String("")).getClass().getName()以上代码运行后,输出java.lang.String
    很明显我们可以看出,getClass()方法是由对象调用
    并返回这个对象所在最小范围内的类名
    所以((Base)s).getClass().getName())是Sub2,((Base)s).FOO
    很明显,static字段由类来调用,而父类中有FOO这个字段,是父类的引用指向子类的对象,说具体点就是强制类型转换,所以调用的是父类的方法
    所以是foo
      

  9.   

    public class Base{
        public static final String FOO = "foo";
        public static void dip(){
         System.out.println("1");
        }
        public void dip2(){
         System.out.println("2");
        }
        public static void main(String []arg){
            Base b = new Base();
            Base s = new Sub();
            b.dip();
            s.dip();
            b.dip2();
            s.dip2();
            System.out.println(Base.FOO);
            System.out.println(Sub.FOO);
            System.out.println(b.FOO);
            System.out.println(s.FOO);
            System.out.println(((Base)s).FOO);//A处        System.out.println("(Base)s  :  getClassName = " + ((Base)s).getClass().getName());//此处输出为Sub,为何A处输出却不是Sub.Foo 的值bar,而是foo呢??[/color]    }
    }
    }
    class Sub extends Base{
        public static final String FOO = "bar";
        public static void dip(){
         System.out.println("2");
        }
        public void dip2(){
         System.out.println("4");
        }
    }
    //输出
    1
    1
    1
    4
    foo
    bar
    foo
    foo
    foo
    (Base)s  :  getClassName = com.code.Sub如果是类变量或者类方法父类引用指向子类对象是不会发生动态绑定的,实例方法才会出现运行时多态,getClass()是实例方法,所以会执行子类的getClass();,当然前提是父类要有这个方法
      

  10.   


    父类的引用指向子类的对象,我承认说反了,但你说upcasting不是多态的表现?Luca Cardelli和Peter Wegner将多态分为两大类—-特定的和通用的—-四小类:强制的,重载的,参数的和包含的。其中包含的就包括向上转型
      

  11.   

    Base b = new Sub(); b.something.... 和 Sub s = new Sub(); ((Base)s).something....
    好像一个效果,我刚刚试了下
    public class Base{
       
        public void dip(){
         System.out.println("3");
        }
        public static void main(String []arg){
            Base b = new Base();
            Base b2 = new Sub();
            Sub s = new Sub();
            b.dip();
            b2.dip();
            s.dip();
    }
    }
    class Sub extends Base{
       
        public void dip(){
         System.out.println("4");
        }
    }
    //输出
    3
    4
    4
      

  12.   

    举个最简单的例子吧!
    class A {
       public void f() {
          System.out.println("A");
       }
    }class B extends A {
       public void f() {
          System.out.println("B");
       }
    }Public class Test {
      public static void main(String arg[]) {
         B b = new B();
         b.f();      
         ((A)b).f();
      }
    }这就是向上转型时体现的多态!
      

  13.   


    够别扭的,你这个例子感觉就是为了多态而upcasting
    再看看另一位同志的原话多态怎么也是要动态调用子类的方法吧,
    这个扯到调用静态变量不说,调用的还是父类的变量, 
    讲难听点就是乱搞upcasting和多态,看到upcasting和貌似的多态就瞎搅在一起
      

  14.   

    丫丫嘀!!
    搞得我更乱了!!!我只是不明白为什么A处是输foo(现在还是没明白,恕愚钝,望路过的哥哥姐姐们给个明白的解释,),没料到竟然引来口舌之争,罪过罪过
    谢谢
      

  15.   


    那是class A的东西,是静态变量
    只有method才有override,才有多态的概念,
    既然强制转换成了A类型的,当然调A.FOO