9

根据 JLS 7,5.1.6 缩小参考转换

• 从任何数组类型 SC[] 到任何数组类型 TC[],前提是 SC 和 TC 是引用类型,并且存在从 SC 到 TC 的缩小引用转换。

Object[] objArr = {"a","b","c"};
String[] strArr = (String[])objArr; // ClassCastException

在上面的示例中,objArr 和 strArr 都是引用类型,并且存在从 Object 到 String 的窄引用转换。

Object obj = "a";
String str = (String)obj;

但以下代码工作正常:

Object[] objArr = (Object[])java.lang.reflect.Array.newInstance(String.class, 3);
String[] strArr = (String[])objArr;

我想问一下java用来进行强制转换的规则。据我所知,这两个示例之间的区别在于,在第一个示例中,objArr 是一个 Object 数组,其组件类型为 Object。第二个是一个对象数组,其组件类型为 String。

请注意,我不是在问如何进行转换,也不是向我展示如何使用 Arrays.copyOf 或其他库进行转换。

4

3 回答 3

7
Object[] objArr = {"a","b","c"};
String[] strArr = (String[])objArr;

随之而来的问题是哪个是s 而不是s{"a","b","c"}的数组。ObjectString

这就像做如下的事情 -

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

以下情况也不例外——

Object[] objArr = new String[] {"a","b","c"}; //Which is the case when you are using reflection
String[] strArr = (String[])objArr; //No exception

这就像做如下的事情 -

Object obj = new String();
String str = (String) obj;
于 2012-10-02T15:20:48.103 回答
1

第一个示例中的“objArr”是 Object[] 类型。第二个示例中的“objArr”是 String[] 类型。

而 String 扩展 Object(String 是 Object 的一种类型) String[] 不扩展 Object[](String-Array Object 不是 Object-Array 的类型)

在第一个示例中,您将 Strings 放入 Object[](Object-Array)对象并不会使其成为 String[](String-array):

Object[] objArr = {"a","b","c"};
System.out.println(objArr instanceof Object[]);//true
System.out.println(objArr instanceof String[]);//false

String[] objArr2 = {"a", "b", "c"};
System.out.println(objArr2 instanceof Object[]);//false
System.out.println(objArr2 instanceof String[]);//true

== 关于协方差

这不是我完全掌握的东西,但这是我从中得到的:

在 Java 中,数组是协变的,泛型不是。这意味着这有效:

Object[] o = new String[3];

这不会:

//ArrayList<Object> o = new ArrayList<String>(); //compile time error

此外,这有效:

function1(new String[2]);
static void function1(Object[] o) {

    }

这不会:

//function2(new ArrayList<String>()); //compile time error
 static void function2(ArrayList<Object> o) {

    }

泛型受到这样的限制是有充分理由的,但这不是本次讨论的重点。

但是我相信这并不是真正关于协方差的讨论,而只是关于如何在 Java 中实现某些类。String[] 类型的对象也是 Object[] 类型的对象(带有所有不好的东西),因此能够这样写是正常的:

Object[] o = new String[3];

但是,由于数组的协方差,因为您可以将 String[] 视为 Object[] 并且在 Object[] 中您可以放置​​任何类型的类型,您可以专门将 Strings 放入对象数组中。IE你可以有这个:

Object[] o = //whatever kind of array;
o[0] = //whatever kind of instance;

然而,这并没有改变最后一个示例中的 o 是 Object[] 类型的事实,因此您不能将其强制转换为 String[]。

于 2012-10-02T15:24:53.073 回答
0
Object[] objArr = {"a","b","c"};
String[] strArr = (String[])objArr; // ClassCastException

在上面的示例中,objArr 和 strArr 都是引用类型,并且存在从 Object 到 String 的窄引用转换。

请注意,您正在从Object 数组引用转换为String 数组引用。因此缩小不适用,因为您没有将单个Object引用转换为String引用。

于 2012-10-02T15:26:08.160 回答