java强转与继承关系的加深理解:object[]的数组无法强转为String[]的数组

在运行下面这段代码时报了一个无法强转的错误Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

public class Demo {
    public static void main(String[] args) {

        ArrayList<String> stringArrayList = new ArrayList<String>();
        stringArrayList.add("abc");
        stringArrayList.add("efg");
        stringArrayList.add("hij");
        
        String[] s = (String[]) stringArrayList.toArray();
    }
}

一开始考虑的是,明明stringArrayList.toArray()作为一个数组其中的元素都来自String类型的字符串,但为什么不能强转。其实不能强转的原因在于stringArrayList.toArray()中的元素虽然来自”String“类型,但是该数组却是一个Object[]类型,自然也无法强转为String[]类型。换句话说一个Object[]类型的对象无法强转为String[]类型的对象。另外这里如果要强转只能将数组中的元素单独拿出来,对单个元素进行强转。为了更清楚的说明我们运行下面这段代码:

public class Demo {
    public static void main(String[] args) {
        String[] s1 = {"abc", "efg", "hij"};
        Object[] s2 = s1;
        String[] s3 = (String[]) s2;  // 可以强转

        Object[] s4 = {"abc", "efg", "hij"};
        String[] s5 = (String[]) s4;  // 报错,不可以强转
    }
}

考虑上述代码中为什么s2虽然是Object[]类型但能够强转为’String[]'类型的s3。原因在于变量s2虽然是Object[]类型,但是其指向了一个String[]类型的对象,‘String[]’类型与’Object[]'类型是存在继承关系的。而下面的s4之所以不能强转为s5是因为s4变量所指对象类型为Object[]s5类型不存在继承关系。

总结

多态是面向对象的三大特性之一,它涉及父类/接口的变量引用子类/实现类的对象。一个类型能否向上转型(强转)关键是看该变量所指向对象与目标类型是否存在继承关系,如果存在则可以强转。

这里有个容易忽视的点是一个变量的类型不一定就是其所引用对象的真正的类型,因为多态的原因还可能是其亚类型/或是接口类型。

原文地址:https://www.cnblogs.com/bitbitbyte/p/12536574.html