gpt4 book ai didi

java - 为什么在推断数组类型时 java 类型不安全?

转载 作者:搜寻专家 更新时间:2023-10-30 21:10:35 24 4
gpt4 key购买 nike

我正在研究泛型,令我惊讶的是,以下代码可以编译:

class A {}
class B extends A {}

class Generic<T> {
private T instance;
public Generic(T instance) {
this.instance = instance;
}
public T get(){ return instance; }
}

public class Main {
public static void main(String[] args) {
fArray(new B[1], new Generic<A>(new A())); // <-- No error here
}

public static <T> void fArray(T[] a, Generic<? extends T> b) {
a[0] = b.get();
}
}

我希望 T推断为 B . A不扩展 B .那么为什么编译器不提示呢?

T似乎被推断为Object ,因为我可以传递 Generic<Object>

此外,在实际运行代码时,它会抛出一个 ArrayStoreExceptiona[0] = b.get(); 上行。

我没有使用任何原始泛型类型。我觉得如果 T 可以通过编译时错误或至少警告来避免此异常。实际上被推断为B .


当使用 List<...> 进一步测试时等效:

public static void main(String[] args) {
fList(new ArrayList<B>(), new Generic<A>(new A())); // <-- Error, as expected
}

public static <T> void fList(List<T> a, Generic<? extends T> b) {
a.add(b.get());
}

这确实会产生错误:

The method fList(List<T>, Generic<? extends T>) in the type Main is not applicable for the arguments (ArrayList<B>, Generic<A>)

和更一般的情况一样:

public static <T> void fList(List<? extends T> a, Generic<? extends T> b) {
a.add(b.get()); // <-- Error here
}

编译器正确识别第一个 ?可能比第二个 ? 在继承层次结构中更靠下.

例如如果第一个?B第二个?A那么这不是类型安全的。


那么为什么第一个示例没有产生类似的编译器错误呢?这只是一个疏忽吗?还是有技术限制?

产生错误的唯一方法是显式提供类型:

Main.<B>fArray(new B[1], new Generic<A>(new A())); // <-- Not applicable

除了this article,我没有通过自己的研究真正找到任何东西从 2005 年开始(泛型之前),其中讨论了数组协变的危险。

数组协变似乎暗示了一种解释,但我想不出一个。


当前jdk是1.8.0.0_91

最佳答案

考虑这个例子:

class A {}
class B extends A {}

class Generic<T> {
private T instance;
public Generic(T instance) {
this.instance = instance;
}
public T get(){ return instance; }
}

public class Main {
public static void main(String[] args) {
fArray(new B[1], new Generic<A>(new A())); // <-- No error here
}

public static <T> void fArray(T[] a, Generic<? extends T> b) {
List<T> list = new ArrayList<>();
list.add(a[0]);
list.add(b.get());
System.out.println(list);
}
}

如您所见,用于推断类型参数的签名是相同的,唯一不同的是 fArray() 只读取数组元素而不是写入它们,使得 T -> A 推理在运行时完全合理。

并且编译器无法判断您的数组引用将在方法的实现中用于什么。

关于java - 为什么在推断数组类型时 java 类型不安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37024513/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com