b2的类型是实际赋给的类型,虽然其使用看起来是声明的类型
b2 instanceof B   结果是 true
b2 instanceof A   结果也是 true

解决方案 »

  1.   

    我觉的这是一个多态的问题。方法调用的是 new 出来的那个对象。
    而参数则相反
      

  2.   

    老兄你跟一下。我在B中再添加方法:
    public String getS() {
    return s;
    }
     A b2 = new B();
    其实是生成了一个子类B的对象,其中含有
    String s(A)="class : A";
    String s(B)="class : B";(其实这里,B的S如果你改成K或者其他名字会更好理解,他是B的一个“私有”变量,与A无关)和B.method(),B.getS()
    而B.method()复写了A.method();
    可是你把他强制转换成了B的super类。于是b2的s还是A的s,s(B)已经被屏蔽。method已经被复写,而A由于没有getS()方法,所以你无法访问该方法。如此解释楼主不知道明白了否...
      

  3.   

    你的构造函数实际等于:public B() {
    this.s = "class : B";
    }楼主如果把B改成:
    public B() {
    super.s = "class : B";
    }
    也许你就可以看到差别了。
      

  4.   

    顺便一提,你B中所有方法中调用的s都等于this.s,也就是B.s,而在外部调用s就是“对象.s”了。你的对象是A,当然s就是A.s啦
      

  5.   

    launch401(Walking in the Air)  
     
       是不是可以这么理解:动态绑定只绑定方法,而不绑定属性
    ----------------------------------------
    java中的所有绑定都是后绑定(就是所谓的“动态绑定”)
    见TIJ中关于绑定的说明(我的版本不是候老师的那个):7.2.1 方法调用的绑定
    将一个方法调用同一个方法主体连接到一起就称为“绑定”(Binding)。若在程序运行以前执行绑定(由编译器和链接程序,如果有的话),就叫作“早期绑定”。大家以前或许从未听说过这个术语,因为它在任何程序化语言里都是不可能的。C编译器只有一种方法调用,那就是“早期绑定”。
    上述程序最令人迷惑不解的地方全与早期绑定有关,因为在只有一个Instrument句柄的前提下,编译器不知道具体该调用哪个方法。
    解决的方法就是“后期绑定”,它意味着绑定在运行期间进行,以对象的类型为基础。后期绑定也叫作“动态绑定”或“运行期绑定”。若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。
    Java中绑定的所有方法都采用后期绑定技术,除非一个方法已被声明成final。这意味着我们通常不必决定是否应进行后期绑定——它是自动发生的。
    为什么要把一个方法声明成final呢?正如上一章指出的那样,它能防止其他人覆盖那个方法。但也许更重要的一点是,它可有效地“关闭”动态绑定,或者告诉编译器不需要进行动态绑定。这样一来,编译器就可为final方法调用生成效率更高的代码。请注意绑定的概念:将一个**方法**调用同一个**方法主体**连接到一起就称为“绑定”(Binding)。特指方法。  
     
      

  6.   

    恩,自类对父类的方法复写是覆盖型的。当然,用楼主的方法,我们仍然可以调用b.s,a.s,无非就是重载几个方法,用super和this去区分而已.
      

  7.   

    本人也是JAVA初学者,对于这个问题我也感到非常疑惑.JAVA不是号称能动态绑定吗??但是对于类字段属性为什么没有这么做???
    下面是我的理解,从这个简单程序分析,首先编译器装载A b2 = new B();即调用B的构造函数,而B是extends A的,所以先调用A的构造函数,然后再调用B的构造函数,至此,构造完毕。现在看b2.method(),这句没有问题,能执行动态帮定.但是b2.s这句我就看不懂了,按照动态帮定的话,应该会调用B.s,但它为什么会调用A.s呢??楼上有位朋友的意思是包的可见性问题.而且建议换个实例变量,那这样的话,怎么测试动态帮定啊??动态帮定就是需要名称和型别都一样才能产生多态的效果.所以我觉得属性是不是没有动态帮定呢????请懂JAVA的朋友给我一个明确的答复
      

  8.   

    ECNU_SEI_kingsang(myjava) ( ) 信誉:100 这个我已经回答过了.
    ----------------------------------------
    请注意绑定的概念:将一个**方法**调用同一个**方法主体**连接到一起就称为“绑定”(Binding)。特指--方法,而不是“属性”。
    ----------------------------------------
    请发问前先看别人的回复。对于B.s来说,与A.s没有任何关系,一个是this.s,一个是super.s。所以B的String 这个东西是叫s或者k无关紧要。b2构造以后,含
    super.s
    this.s
    super.method()=this.method()
    而,你把b2强制转换成A,则this.s将被屏蔽。属性是不能够被复写的。即使名字一样。把楼主的代码改一下:
    class A {
        String s;
        public A() {
            s = "class : A";
        }
        public void method() {
        }
    }
    class B extends A {
        String k;
        public B() {
            this.k = "class : B";
        }
        public void method() {
            System.out.println("hello world" + k);
        }
    }
    public class Test {    public static void main(String[] args) {
            A b2 = new B();
            b2.method();//调用的实际上是A.method();但是此method已经被B给复写。
            System.out.println(b2.s);//这里你不能访问b2.k,因为b2是A,没有k.(即使实际上b2含有,但是无法通过A的方法访问。)
        }
    }和上面的效果是一样的,不知道看明白没有。
      

  9.   

    to 楼上:多谢解答。我基本搞懂了,实际上就一句话,属性不支持动态帮定。就是说即使属性的名称和super class的属性名称一样,也不能实现象多态那样的机制。这就是我郁闷的地方,为什么JAVA程序设计语言为什么不支持属性的动态帮定。
      

  10.   

    你可以指定super.s来用父类的属性啊。
      

  11.   

    楼上可能没有理解我的意思,如果你用super.s的话,就是唯一确定了类型。我的意思是这样的:class BaseClass {
        public String s;
        public BaseClass () {
            this.s = "baseclass";
        }
    }class _A extends BaseClass{
        public String s;
        public _A () {
            this.s = "_A class";
        }
    }class _B extends BaseClass{
        public String s;
        public _B () {
            this.s = "_B class";
        }
    }class _C extends BaseClass{
        public String s;
        public _C () {
            this.s = "_C class";
        }
    }class _D extends BaseClass{
        public String s;
        public _D () {
            this.s = "_D class";
        }
    }public class FieldInstanceTest {
        public static void main (String[] args) {
            BaseClass[] b = new BaseClass[4];
            b[0] = new _A();
            b[1] = new _B();
            b[2] = new _C();
            b[3] = new _D();
            for (int i = 0; i < b.length; i++) 
                System.out.println(b[i].s);//我希望打印出_A class
                                           //            _B class
                                           //            _C class
                                           //            _D class,然而我看到属性并不支持动态
    //帮定,我现在懂了。我的问题是JAVA的设计者为什么不让属性动态帮定,对于这个例子,我只能
    //通过 创建类似_A a = new _A()的对象,然后a.s,b.s,c.s,d.s来实现我想要的结果,这样不是很麻烦吗?
        }
    }
      

  12.   

    Java中动态创建类的类Proxy,也是只支持method而不支持field,也许是因为jvm技术的问题,或者设计者为了强迫用户封装吧,因为oo不鼓励直接调field