JAVA引用类型强制类型转换

来源:互联网 发布:淘宝可以货到付款吗? 编辑:程序博客网 时间:2024/05/22 16:38

       今天在看《Java核心技术》卷一的泛型程序设计章节的时候,提到了通过捕获异常后,然后强制类型转换为RuntimeException类型,达到unchecked异常抛出。不必必须通过try-catch-finally语句来处理异常的目的。但感觉违反了类型强制类型转换的规则。所以思考之。

       强制类型转换分两类:基本数据类型的强制类型转换、引用类型的强制类型转换。这里讲下引用类型强制转换。被转换的如果是子类,那么自然而然就可以换;被转换的是父类,那么就需要强制转换,如果父类的引用实际指向的是子类对象,那么转换成功,如果不是转换不成功。

      通过这篇文章可以理解得更清晰。同时还看见评论说,这个概念和虚拟机的内存模型一并讲更清晰。

但是现在看下下面这个代码:

package reflect;import java.io.FileNotFoundException;  public class Main {  public static void main(String[] args) {  new Block() {  @Override  public void body() throws Exception {  throw new FileNotFoundException();  }  }.toThread().start();  }  }  abstract class Block {  public abstract void body() throws Exception;  public Thread toThread() {  return new Thread() {  public void run() {  try {  body();  } catch (Throwable t) { //将Throwable的异常包装为了RuntimeExceptionBlock.<RuntimeException>throwAs(t);}  }  };  }  @SuppressWarnings("unchecked")public static <T extends Throwable> void throwAs(Throwable e) throws T {  throw (T) e;  }  }  


       这个地方body抛出的是,一个FileNotFoundException,它可以转换为Throwable,因为Throwable是它的父类。但是在catch语句中把他强制转换为RuntimeException是不行的。因为RuntimeException不是FileNotFoundException的父类。那怎么程序可以通过呢?

       其实我理解的这里的道理就是编译器被欺骗了:

  • 当泛型申明为RuntimeException时,编译器就认为这是一个不需要捕获的异常,
  • 实际代码执行的过程中,由于擦除的关系,擦除后T被Throwable代替。在运行时强制转换又不会出问题。

       数组的强制类型转换是一样的 

Object obj1[] = {"t1","t2"};  //第一个数组Object obj2[] = new String[]{"t1","t2"};//第二个数组


       这里需要注意一个问题就是,基本数据类型的数组不能强制转换为Object[]数组,因为基本数据类型不是继承于Object的。

int[] i = new int[]{1,3,4};//Cannot cast from int[] to Object[]//Object[] objects = (Object[])i;

       数组的类型取决于初始化的时候是什么,而不是取决于数组内部装的是什么类型的。 数组的类型确定了之后,数组可以装的对象的大类型就确定了,只能是数组的类型或者其子类型。 所以,第一个数组的类型就是Object,他是不能向下转型为String。 第二个数组的类型是String(虽然申明是Object,但是实际是String),所以他可以向下转型为String[]类型。