几个Java泛型问题

几个Java泛型问题,java,generics,Java,Generics,我目前正在从一本书中学习Java泛型,有一些事情我不太了解 假设我有一个参数化类: class MyClass<T> { T item; public T getItem() { return item; } // ... } 我具体以什么方式丢失了ArrayList可以提供的任何类型安全性? 请注意,我并不是要说明使用参数化类型的数组的理由,我确信集合实际上表现得更好,我只是想了解它们为什么会这样做,以及使用数组会出现什么问题。为什么“更安全”使用

我目前正在从一本书中学习Java泛型,有一些事情我不太了解

假设我有一个参数化类:

class MyClass<T> { 

    T item;

    public T getItem() { return item; }

    // ...
}
我具体以什么方式丢失了
ArrayList
可以提供的任何类型安全性? 请注意,我并不是要说明使用参数化类型的数组的理由,我确信集合实际上表现得更好,我只是想了解它们为什么会这样做,以及使用数组会出现什么问题。

为什么“更安全”使用泛型集合与裸数组是因为编译器增加了额外的保证,即您的代码将执行预期的操作,因为不太可能由于部件的编码错误而混合对使用不同类型参数创建的对象的引用

例如,将
MyClass
的混合物添加到
MyClass
数组中是完全合法的:

MyClass<Integer> mcInt = new MyClass<Integer>();
MyClass<String> mcString = new MyClass<String>();
MyClass[] array = new MyClass[] { mcInt , mcString }; 
...
MyClass<String>[] typedArray = (MyClass<String>[]) array;
欢迎您使用裸数组,但这样做会丢失编译器所做的额外检查。实际上,使用不安全数组是可以的,如果这些数组是私有字段或局部变量,当您确信您的代码实际上是安全的(如果您使用泛型,编译器会保证它是安全的)时,使用@SuppressWarnings(“unchecked”)会格外小心并消除警告


根据我的经验,大多数情况下,只要有可能,最好只使用泛型集合,但有时您可能会遇到这样的情况:由于性能原因,不安全的替代方案更方便,或者仅仅因为安全的替代方案会导致更麻烦的代码。

不,您不能,至少不能不使用它。编译器保护您不将
MyClass
放入
ArrayList
中。当然,您可以通过明智地添加类型转换来避免编译错误,但这样做是愚蠢的。对,但数组也是如此<代码>MyClass[]foo=新的MyClass[10];foo[0]=新的MyClass();//错误编译器不会警告您不要在数组中存储错误的内容。它确实试图阻止你在ArrayList中存储错误的内容。我认为这本书没有很好地解释这一点,或者你已经断章取义了。问题是,当您尝试创建一个泛型参数类型的数组时,例如在MyClass中,您会执行
T[]items=(T[])新对象[10]。请注意,数组和泛型实际上不能很好地配合使用。将东西存储在
阵列列表中
。感谢您的回答,但我仍然没有看到任何额外的类型安全性。您的
list
类型为
list
,因此,是的,当您尝试添加
MyClass
类型的对象时,编译器会发现一个错误。但使用数组时也会发生同样的情况:
MyClass[]arr=newmyclass[10];arr[0]=新的MyClass();//错误
@yakmiras问题是数组可能已经包含了一个MyClass实例,如我在代码示例中所示。。。损害已经造成了。通过强类型引用的进一步访问不会造成任何额外的损害。@yakmiras另一种情况是,某些其他组件使用具有不同泛型类型参数的变量或字段访问同一数组,在这种情况下,您可以向同一数组添加混合元素。一旦你对一个不安全的演员阵容感到满意,那么为什么不选两个或四个呢?@yakmiras,底线是只要你处理好业务,任何一个解决方案在实践中都是同样安全的。。。然而,由于编码并不完美,而且总是有bug隐藏在周围,随着时间的推移(代码行),如果您在选择不使用不安全强制转换时继续使用不安全强制转换,那么很可能会因此产生额外的bug……对吧,所以我想区别在于您无法执行以下操作:
List foo=new ArrayList(); /* 添加MyClass*/List bar=foo;//的实例错误
MyClass<String>[] foo = new MyClass[10];
// Please don't comment about any problems related to bounds etc. This class should serve purely 
// for demonstration of the core issue I'm trying to understand
public class MyClass<T> {

    private T[] items = (T[]) new Object[10];

    private int size = 0;

    public void addItem(T item) {
        items[size++] = item;
    }

    public T getItem(int index) {
        return items[index];
    }
}
MyClass<Integer> mcInt = new MyClass<Integer>();
MyClass<String> mcString = new MyClass<String>();
MyClass[] array = new MyClass[] { mcInt , mcString }; 
...
MyClass<String>[] typedArray = (MyClass<String>[]) array;
MyClass<Integer> mcInt = new MyClass<Integer>();
MyClass<String> mcString = new MyClass<String>();
List<MyClass<String>> list = new ArrayList<MyClass<String>>(); 
list.add(mcString); // is ok.
list.add(mcInt); // won't compile.