谨慎使用向下转型

来源:互联网 发布:林书豪16赛季数据 编辑:程序博客网 时间:2024/05/20 03:07

关于转型

向上转型一般是安全的,因为基类不会具有大于导出类的接口。

向下转型可能是不安全的,我们可能无法将一个基类正确的处理为想要转为的导出类,比如你不知道一个几何图形究竟是圆,或是三角形和正方形。

在JAVA中,所有的转型都会在运行期进行检查,即使在编译期已经检查过一次。如果在运行期转型出错,便会返回一个ClassCastException。

这种运行期间的类型检查叫做RTTI。

转型不难理解,向上转型可以概括为:父类引用指向子类对象。

相似的有工厂方法设计模式:把使用实现了某一接口的类创建的对象的引用赋给该接口声明的接口变量(或许也可以算作向上转型?)

Object obj = new String();//与List list = new ArrayList();

谨慎使用向下转型

向下转型就是与向上转型进行了相反的操作,但是要时刻注意你的转型操作,确保它是安全的,下面的例子便是不安全的转型操作

Object obj = new Object();String str = (String)obj; //ClassCastException

上面的例子无法被正常执行,因为obj指向的可能是任何的Object的子类对象,例如:

Object aInt = new Integer(1);String str = (String)obj;

想要进行向下转型,就必须要确保数据的安全转型,即:

public class FirstJava {    public static void main(String[] args) {        Object aString = new String("Hello World");        String downCastingString =(String)aString;        System.out.println(downCastingString);    }}//~out://Hello World

关于向下转型,个人理解比较常用的一个例子是ArrayList中的toArray()方法,事实上我也在这里犯过错误:

ArrayList<String> allStrs = new ArrayList<>();String[] stringArray = (String[]) allStrs.toArray();

这样写是不行的

对于ArrayList类,重写的toArray()方法会返回一个Object[]数组,而String[]是它的子类,剩下的我们已经分析过了。

想要让这个转型正确工作,我们需要调用toArray()的一个重载方法:public T[] toArray(T[] a);

public <T> T[] toArray(T[] a) {    if (a.length < size)        // Make a new array of a's runtime type, but my contents:        return (T[]) Arrays.copyOf(elementData, size, a.getClass());    System.arraycopy(elementData, 0, a, 0, size);    if (a.length > size)        a[size] = null;    return a;}

浏览源码,我们可以看到这个方法在返回数组时,我们可以自行生成(调用copyOf)一个确定类型的数组,而从源码中可以看到这个方法返回的就是一个对应类型的数组了,从而确保向下转型的安全性,因此我们对代码做如下改下改写便不会抛出异常了:

public class FirstJava {    public static void main(String[] args) {        ArrayList<String> allStrs = new ArrayList<>();        allStrs.add("str1");        allStrs.add("str2");        allStrs.add("str3");        String[] stringArray = allStrs.toArray(new String[allStrs.size()]);        for (String str : stringArray) {            System.out.println(str);        }    }}//~out:// str1// str2// str3
原创粉丝点击