Java 泛型对象数组,其中泛型对象的上界与对象的上界不同

Java 泛型对象数组,其中泛型对象的上界与对象的上界不同,java,generics,Java,Generics,谁能解释以下场景中发生的情况?为什么一个给出错误,而另一个没有 public class TestClass<T extends Comparable<T>> { protected T []items; public TestClass(int size, T... values) { items = (T[]) new Object[size]; for (int v = 0; v < Math.min(size

谁能解释以下场景中发生的情况?为什么一个给出错误,而另一个没有

public class TestClass<T extends Comparable<T>> {
    protected T []items;

    public TestClass(int size, T... values) {
        items = (T[]) new Object[size];
        for (int v = 0; v < Math.min(size, values.length); v++) {
            items[v] = values[v];
        }
    }

    public T getItem() {
        return items[0];
    }

    public static void main(String []args) {
        System.out.println(new TestClass<>(2, 6).getItem()); // Error
    }
}
但这样做并不是:

System.out.println(new TestClass<>(2, 6).getItem()); // Prints 6
System.out.println(新的TestClass(2,6).getItem());//印刷品6

还有人觉得java泛型类型有点不一致吗?

我相信你的问题就在这里

items = (T[]) new Object[size];

类对象[]不扩展Comparable(或任何接口),因此,您不能说
Comparable c=(Comparable)(new Object())
,也不能将对象[]强制转换为Comparable[],如果它不是最初的对象。

根据问题的更改而更新

如果泛型类型参数上声明了上限,则编译器将在调用返回泛型类型的方法或为泛型类型的变量赋值时,插入对正确类型的转换,以确保类型安全

在第一种情况下,由于
Comparable
T
的上限,编译器将强制转换插入构造函数中的
Comparable[]
,因为数组被分配给
T[]
。但是,所分配的实际上是一个
对象[]
,因此强制转换失败

在第二种情况下,没有上限,因此编译器不会在构造函数中插入对
Comparable[]
的转换,因此没有失败的转换

要使第一种情况成功,即使在泛型类型参数上声明了上限,也应遵循的建议创建泛型数组。这需要传入
Class
对象,以便创建适当类的数组

@SuppressWarnings("unchecked")
public TestClass(int size, Class<T> clazz, T... values) {
    items = (T[]) Array.newInstance(clazz, size);
    // ...
}
@SuppressWarnings(“未选中”)
公共测试类(整型大小、类类别、T…值){
items=(T[])Array.newInstance(clazz,size);
// ...
}

如果您对
(T[])新对象[大小]没有意见
T
的上限为
Object
时,那么当
T扩展到Comparable
时,类似的事情将是:

(T[]) new Comparable[size]

原因是
T
被擦除到其上限。因此,在
T
的上限为
Object
的情况下,强制转换被擦除为对
Object[]
的强制转换,这是正常的。但是,当
T
的上限为
Comparable
时,强制转换将被删除为
Comparable[]
的强制转换,如果对象的运行时类为
object[]
,则这是不正常的。将其更改为
Comparable[]
可以解决此问题。

我认为由于类型擦除,这应该由JVM处理?你有什么建议可以解决这个问题呢?也许我能想到的最简单的方法就是遵循java的ArrayList使用的方式;使用对象[](或者因为值是可比较的,所以使用可比较的[]),而不是T[],并将元素添加到该数组中。当您想要从数组中检索数据时,只需检索内容并将其强制转换为TSee my edit,我无法更改数组的类型,因为我无法访问该类型唯一的方法是使用另一种方法(我不太喜欢,但在本例中效果更好),这是TargetMan所做的,并使用array.newInstance()对于对象的运行时类,您正在创建一个作为参数传入的数组和一个强制转换。您这样说是什么意思?:“我没有访问数组创建方法的权限?”实际上,如果仔细观察,两者都返回type
T
。如果helps@Smac89我看得太快了。我已经纠正了演员插入的位置。好的,知道了。但正如我在第一篇文章中提到的,我没有访问数组创建方法的权限,因为这个类实际上是另一个类的子类,而创建数组的是超类。我会到处找其他的methods@Smac89更新是为了回应你更新的问题。我也在快速阅读,错过了你的第一段。似乎做
this.items=(T[])新的可比[cap]
已经解决了这个问题,我相信我在最初的帖子中已经解决了这个问题。不过还是有一些东西我发现还没有修好,如果你可以拿一个look@Smac89:是的,这是错误地假装数组是
T[]
的危险,而不是--
T
在类内被擦除到其上限,因此不会在类内造成任何问题。但是您不能将它公开给类的外部,在类的外部,它们为
T
假定一个具体的类型参数。如果在运行时不知道
T
,就不可能向类外部公开正确的数组类型。
items = (T[]) new Object[size];
@SuppressWarnings("unchecked")
public TestClass(int size, Class<T> clazz, T... values) {
    items = (T[]) Array.newInstance(clazz, size);
    // ...
}
(T[]) new Comparable[size]