Can I create an array whose component type is a concrete parameterized type? 我可以创建一个泛型数组嘛?

Can I create an array whose component type is a concrete parameterized type? 我可以创建一个元素类型为具体的参数化类型的数组嘛(我可以创建一个泛型数组嘛)?

原文地址:http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ104

关键点

泛型数组被禁止的原因 
类型擦除后会导致数组元素类型不确定性,举例

Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10]; // illegal 
Object[] objArr = intPairArr;
objArr[0] = new Pair<String,String>("",""); // should fail

我们期望intPairArr仅仅存储Pair<Integer,Integer>类型的键值对,但是类型擦除后,这个数组会变为这样:

Pair[] intPairArr = new Pair[10];

数组仅保留了其原始类型(raw type)。这样一来,数组就会接受任何类型的键值对了,如Pair<String,String>。这就破坏了数组元素单一性原则。 
一个特殊的情况

Node<?>[] nodes = new Node[10]; //这是可以的

全文翻译

No, because it is not type-safe.

不可以,因为它不是类型安全的。

Arrays are covariant, which means that an array of supertype references is a supertype of an array of subtype references. That is, Object[] is a supertype of String[] and a string array can be accessed through a reference variable of type Object[] .

数组是协同变化的。这个就意味着一个超类引用的数组是一个子类引用数组的超类。也就是,Object[]是String[]的一个超类,因此一个字符串数组可以被一个Object[]类型的引用变量所引用。

Example (of covariant arrays):

一个(协同数组的)例子:

Object[] objArr = new String[10];  // fine 
objArr[0] = new String();

In addition, arrays carry runtime type information about their component type, that is, about the type of the elements contained. The runtime type information regarding the component type is used when elements are stored in an array in order to ensure that no “alien” elements can be inserted.

此外,数组携带了关于其成分类型的运行时类型信息,也就指携带了关于所包含的元素的类型信息。关于元素类型的运行时类型信息在元素存入一个数组时被使用,以确保没有“异族”元素可被插入。

Example (of array store check):

一个(数组存储检查)的例子:

Object[] objArr = new String[10]; 
objArr[0] = new Long(0L); // compiles; fails at runtime with ArrayStoreException

The reference variable of type Object[] refers to a String[] , which means that only strings are permitted as elements of the array. When an element is inserted into the array, the information about the array’s component type is used to perform a type check - the so-called array store check. In our example the array store check will fail because we are trying to add a Long to an array of String s. Failure of the array store check is reported by means of a ArrayStoreException .

Object[]类型的引用变量引用了一个String[]数组,这个String数组仅仅接受字符串类型的元素。当一个元素插入到了数组,这个关于数组元素类型的信息就会被用于类型检查。这个类型检查也就是所谓的数组储存检查。在我们的例子中,检查会失败,因为我们正在尝试向一个String数组中添加Long对象。数组存储检查失败是通过抛出ArrayStroreException异常来表达的。

Problems arise when an array holds elements whose type is a concrete parameterized type. Because of type erasure, parameterized types do not have exact runtime type information. As a consequence, the array store check does not work because it uses the dynamic type information regarding the array’s (non-exact) component type for the array store check.

当一个数组持有了这样的元素时就会有问题——元素的类型是一个具体的参数化类型(泛型元素)。由于类型擦除,参数化类型并不具有实际的运行时类型信息。结果就是数组存储检查失效了,因为检查使用了关于数组元素的(非准确)类型信息。

Example (of array store check in case of parameterized component type):

一个(关于参数化元素类型的数组存储检查)案例:

Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10]; // illegal 
Object[] objArr = intPairArr;
objArr[0] = new Pair<String,String>("",""); // should fail, but would succeed

If arrays of concrete parameterized types were allowed, then a reference variable of type Object[] could refer to a Pair<Integer,Integer>[] , as shown in the example. At runtime an array store check must be performed when an array element is added to the array. Since we are trying to add a Pair<String,String> to a Pair<Integer,Integer>[] we would expect that the type check fails. However, the JVM cannot detect any type mismatch here: at runtime, after type erasure, objArr would have the dynamic type Pair[] and the element to be stored has the matching dynamic type Pair . Hence the store check succeeds, although it should not.

如果具体的参数化类型被允许,那么一个Object[]类型的引用变量就可以去引用一个Pair<Integer,Integer>[]对象,正如案例所示的那样。在运行时,当一个数组添加了一个元素,数组存储检查必须进行。由于我们正在尝试把一个Pair<String,String>添加到一个Pair<Integer,Integer>[]数组当中,那么我们预期类型检查会失败。然而,JVM无法在此检查出任何的类型不匹配:在运行时,类型擦除后,objArr对象会拥有一个动态类型Pair[],并且存储的元素已经和动态类型Pair相匹配了,因此类型检查成功,虽然理论上并非如此。

If it were permitted to declare arrays that holds elements whose type is a concrete parameterized type we would end up in an unacceptable situation. The array in our example would contain different types of pairs instead of pairs of the same type. This is in contradiction to the expectation that arrays hold elements of the same type (or subtypes thereof). This undesired situation would most likely lead to program failure some time later, perhaps when a method is invoked on the array elements.

如果允许我们声明持有具体的参数化类型元素的数组,那么我们就会遇到一个不可接受的情景。案例中的数组将会包含多种类型的键值对,而非单一类型。这与对数组持有单一类型(或它的子类型)元素的期望背道而驰。这种不令人满意的情景很有可能将在随后把程序引入到错误当中,也许这个时刻就在一个方法调用数组元素时。

Example (of subsequent failure):

一个(随后而失败的)例子:

Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10]; // illegal 
Object[] objArr = intPairArr;
objArr[0] = new Pair<String,String>("",""); // should fail, but would succeed
Integer i = intPairArr[0].getFirst(); // fails at runtime with ClassCastException

The method getFirst is applied to the first element of the array and it returns a String instead of an Integer because the first element in the array intPairArr is a pair of strings, and not a pair of integers as one would expect. The innocent-looking assignment to the Integer variable i will fail with a ClassCastException , although no cast expression is present in the source code. Such an unexpected ClassCastException is considered a violation of type-safety.

getFirst()方法被应用到了数组的第一个元素当中,它会返回一个String而非一个Integer,因为数组intPairArr的第一个元素是一个对字符串,而非期望中的一对整数。这个对整型变量i的一个平凡的赋值会失败,且抛出一个ClassCastException,虽然在源代码中没有表现出类型转换异常。这样的一种意外的类型转换异常就是一种对类型安全的违背。

In order to prevent programs that are not type-safe all arrays holding elements whose type is a concrete parameterized type are illegal. For the same reason, arrays holding elements whose type is a wildcard parameterized type are banned, too. Only arrays with an unbounded wildcard parameterized type as the component type are permitted. More generally, reifiable types are permitted as component type of arrays, while arrays with a non-reifiable component type are illegal.

为了防止程序不是类型安全的,所有持有具体的参数类型元素数组都是非法的。同理,持有通配符参数化类型元素的数组也是不允许的。只有非受限通配符参数化类型元素的数组才被允许。更一般的讲,可具体化类型可允许作为数组元素类型,不可具体化类型则不可以。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值