本帖最后由 hbin_apple 于 2010-09-03 19:32:53 编辑

解决方案 »

  1.   

    Java是自动转换的。 T3 -> T1t1 现在是一个 T1对象, 向孙子类强制转换,使不可行的。我们可以用内存原理来解释:
    *1处: T3对象创建时,它包括了T1和T2的内存数据。 t1是指向T3中的T1部分。
    *2处: T1对象创建, 它没包括T2和T3的内存数据。那么我们就不能孙子类强制转换。
      

  2.   



    Java自动进行强制类型转换只会发生在值类型与他的封装类中。这些类型和他们的封装类包括:int-Integer,boolean-Boolean,double-Double,float-Float,char-Character,byte-Byte,long-Long在jdk1.5以前,这种强制进行原始数据类型与他的封装类之间的自动转换是不被支持的。而在jdk1.5以后,这种方式得到支持,即:
    Integer i = 0;可以正常被编译器通过。所以说,所谓的自动进行强制类型转换,就是自动装箱/拆箱的过程,当一个原始数据类型的数据要被它的封装类的类型引用时,就会对其进行装箱操作,反之则是进行拆箱。这种方式也是简化程序员进行编码的方式,去除了必要的强制性代码编写,简化了代码的阅读。 

    T1 t1=new T3();//这里t1的引用是T1类型的。
    T2 t2=(T2)t1;//这里由于t1的引用时T1类型的,无法与T2类型匹配,所以需要强制类型转换。属于向上转型
    向上转型(Upcasting)是安全的。向下转型(Downcasting)是不安全的。原因如1楼所说。
    所以建议采取Downcasting的时候先instanceof...否则后果自负...
      

  3.   

    这两个都是像下转型。
    那么为什么前一句向下转型代码可以,而后一句代码却出错?
    这是因为刚开始的时候,t1指向一个子类T3的对象,所以子类T2的实例对象t2当然也可以指向t1,因为T3是T2的子类,这里是多态啊,父类引用指向子类对象。
    而下面的时候t1是一个父类对象,子类引用t2不能指向父类对象t1。那么如何避免这种在执行向下转型时发生运行时ClassCastException异常?用instanceof就可以了。我们修改一下的代码: 
    class T1{}
    class T2 extends T1{}
    class T3 extends T2{}
    class Test{
      public static void main(String [] args){
      T1 t1=new T3();
      T2 t2=(T2)t1;//合法,发生强制类型转换。*1  t1=new T1();
      if(t1 instanceof T2){//显然t1不是T2啊,就想不能说鸟是麻雀一样
           t2=(T2)t1;
        }
      }
    }
      

  4.   

    更正一下2楼...第一个确实是Downcasting,习惯性看错了哈哈~~抱歉..那么原因就如1楼所言了
      

  5.   

    强制转换这个概念其实容易误解,强制转换本来只能用来描述基本类型的转换,
    比如:float a = 5.0f; int d = (int) a;之所以需要强制转换,是因为这种变量在内存中的布局是不同的,比如 int 是按一般说的二进制分布的,而 Float 则是按 IEEE 浮点数的二进制表示分布在内存的(某几位是指数,某几位是尾数,某个位是+/-号位等),这需要编译器生成转换的指令去将它的不同的位转换成对应的值。而面向对象里面的 cast 在 Java 中,case 仅仅是临时改变可见性,也就是说:
    Parent p = new Child();
    Child c = (Child) p;
    这两句,第一句,我们创建了 Child对象,赋值给 Parent 之后,我们就可以只能看到 Parent 类的属性和方法。在 Child 中新增的 Parent 中没有,就不能使用,这由编译器来检查。而当我们再赋值给 Child 时,用 cast 仅仅是请求编译器再检查一下它是不是合适的,如果合适就再把它的可见性还原。其它你要调用一个对象的某个方法,编译器最后生成的指令其实都是用虚函数调用的方式,也就是相当于动态地调用而不像 C语言那样去链接生成静态二进制代码,类型只是 VM 来确保它是有效的,编译的过程本身”并不那么需要知道类型“。否则的话,我们要用 Java 的反射的话,那岂不是很麻烦?背后的原理就是抽象类型的对象本身从 new 之后就永远不会改变类型(Java 中如此,其它语言不清楚)。上面基本类型和抽象类型的 Cast 的意思是不同的,基本类型会改变内存中数据的分布,而抽象类型的都仅改变可见性,对象本身的状态没有任何变化。