class A {
protected void f() { 
System.out.println("A.f()");
this.g(); 
}
protected void g() {
System.out.println("A.g()"); 
}
}class B extends A {
@Override protected void g() {
System.out.println("B.g()");
}
public void m(){
System.out.println("向上转向 可以调用它");
}
}public class Exer8_10 {
public static void main(String[] args) {
B b = new B();
// automatic upgrade to base-class to call base-class method A.f()
// which,by polymorphism, will call the derived-class method B.g():
b.f();
A a = new B();
B c =(B)new A();
c.m();//注意:向下转型
}
}
这个程序的结果为:
A.f()
B.g()
向上转向 可以调用它
Exception in thread "main" java.lang.ClassCastException: A
at Exer8_10.main(Exer8_10.java:29)请问:
执行 B c =(B)new A();  c.m(); 时new A()创建的A对象中根本没有m()方法 怎么可以调用它呢 如: c.m();
调用后既然抛出了异常 怎么还可以执行呢
谢谢

解决方案 »

  1.   

    执行 B c =(B)new A();  c.m(); 时new A()创建的A对象中根本没有m()方法 怎么可以调用它呢 如: c.m();
    调用后既然抛出了异常 怎么还可以执行呢 因为执行的时候是B类,既然是B类,就有m()方法,但是通过new A()得到的,即没有开辟这块内存,所以抛出异常
      

  2.   


    1.因为c是被声明为一个B的对象引用,当然编译器会让他调用B的方法就像 B c = null; 
        虽然这时候 c 执行null 你仍然可以调用 m方法
    2.ClassCastException 是一个 RuntimeException 所以 你的代码虽然有问题 但是仍然可以执行
      

  3.   

    这个涉及到动态绑定了。对应用类型的变量,运行时Java虚拟机按照它实际引用的对象处理。在运行的时候,子类的对象可以转换成父类的类型,但父类的对象实际无法转换成子类类型。class A{}class B extends A {}B b = new B(); //b引用的是B类型的实例
    A a = (A)b; // 把子类的实例转换成了父类类型
    a.m(); //a引用变量实际引用的是B类型的实例,也就是子类类型,所以在运行的时候,会抛出异常
      

  4.   

    不好意思我说反了,没仔细看你的程序。这么说吧class Base{}class Sub extends Base {    public void m(){};
    }Base b = new Base(); //创建父类的实例Sub s = (Sub)b; //把父类的实例b转换成子类类型;s.m(); //s引用变量实际是引用父类型的实例,但是在父类中没有m()方法。所以代码尽管能编译成功,但是在运行的时候,就要抛出类型转换异常了。不好意思呵呵。
      

  5.   

    1,能不能调用到m()是运行是决定的 因为编译时 B c 你的c要指向哪个对象是不能确定的。
    2,类型并不能改变是前提. 向下转型也是一样. 你的真实类型是什么才可以转成什么类型. 
       就是不能将猫转成狗的意思虽然他们都是动物。
      

  6.   

    我还是没弄明白 如创建new A()对象的时候 在内存中分配了A对象的内存空间 而没有分配B对象的内存空间
    当执行 B c =(B)new A(); 是将c引用指向了这个A对象那块的内存空间 而这块内存中根本没有属于B的m()方法
    那么c.m();怎么能调用得到呢 
      

  7.   

    可不可以这样理解:在强制转换的时候内存分配了东西!这个东西c可以用,但是本身的A不包含这个东西,而编译器对c的理解是A的类型?