为什么我被允许将通用数组声明为实例变量?

gri*_*ime 8 java arrays generics instance-variables

我完全清楚泛型数组不能像这样实例化:

data = new Entry<K, V>[];
Run Code Online (Sandbox Code Playgroud)

这将导致错误:

Cannot create a generic array of Entry<K,V>
Run Code Online (Sandbox Code Playgroud)

那么,为什么我允许声明一个没有错误的泛型类型数组的实例变量?

private Entry<K, V>[] data;
Run Code Online (Sandbox Code Playgroud)

Jon*_*han 4

原则上,约阿希姆·索尔的评论已经是你的答案,但是,我想详细说明一下。

Sun (Oracle) 知道一种称为内存污染的现象,如果通用变量指针指向类型不兼容的对象,这种现象总是会发生。例如可以使用以下代码强制执行此操作:

List<String> list = new ArrayList<String>();
List<Number> numberList = (List<Number>)(List)list;
Run Code Online (Sandbox Code Playgroud)

ClassCastExceptions显然,一旦您开始使用该代码,您就会开始看到。这对于 Sun 在设计泛型时完全没问题,因为您会收到强制警告 RawType/Unchecked conversion。每当发出此警告时,您就知道您的代码未经过 100% 类型检查,并且可能会发生内存污染。

Generics 的总体设计原则是,所有可能的内存污染都由此类警告指示。这就是禁止创建通用数组的原因。假设不是,可能会发生以下情况:

List<String>[] array = new List<String>[5];
Object[] oArray = array // this works without warning and has to for compatibility
List<Object> oList = new ArrayList<Object>();
oArray[1] = oList;
Run Code Online (Sandbox Code Playgroud)

您将在没有任何警告的情况下出现内存污染,并且出于兼容性原因,无法生成警告。这就是 Sun 决定禁止泛型类型数组的原因。然而,变量可能会被声明,因为您会在那里收到未经检查的转换警告,而这正是 Sun 想要的:如果可能发生污染,则发出警告。