奇怪的仿制药问题

问题描述 投票:0回答:6

有谁知道为什么以下代码无法编译并且在编译过程中出现不兼容类型异常?

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test test = new Test();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

}

为什么使用带有无界通配符的 Test 可以解决这个问题? 我使用的是java版本1.6.0_12

java generics
6个回答
8
投票

我将问题解释为为什么当返回类型不依赖于类型参数时

test.getDays()
不返回
List<Integer>
T

当您创建一个对

Test
实例的原始引用的变量时,编译器会删除通过该变量访问的所有泛型(为了向后兼容)。

因为

test
没有指定其类型
<T>
,这也意味着
<Integer>
getDays
被丢弃。


3
投票

与阿德尔的答案略有不同,但你是这个意思吗?

public class Test<T> {

public static void main(String[] args)
{
    Test<Integer> test = new Test<Integer>();

    Integer number = test.getDays().get(0);
}


private List<T> getDays() {
    return new ArrayList<T>();
}

} 

1
投票

试试这个:

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test<Integer> test = new Test<Integer>();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

} 

1
投票

我尝试编译它,但遇到了同样的问题。我认为 OP 不需要解释如何使用泛型。自己尝试一下......奇怪的是它“应该”工作,因为根本没有使用泛型类型 T,因为 getDate 的声明声明它将返回对整数列表的引用。

您可以像这样实例化测试:

Test<JFrame> test = new Test();

...并且它可以编译! (当然你可以在这里使用任何现有的类型...)奇怪的事情...

如果删除通用声明它也可以工作(当然)。


0
投票

编译器无法确定 Test 的实际类型,因为您将其指定为泛型,然后使用原始类型。添加 ?通配符使编译器知道实际的类只能在运行时确定;它不会检查班级类型。

您还可以通过使 Test 类成为非泛型或使 getDays() 返回列表来解决编译问题。


0
投票

当您将变量或字段声明为原始类型时,该字段或变量的所有用法都会丢失所有通用信息,而不仅仅是与原始类型删除的类型变量相关的通用信息。这意味着您对

test.getDays()
的调用返回了
List
而不是
List<Integer>
,即使 Integer 与 T 无关。

© www.soinside.com 2019 - 2024. All rights reserved.