gpt4 book ai didi

java - 在 Java 中强制转换由通用实例类型的 getClass() 返回的类是否总是安全的?

转载 作者:行者123 更新时间:2023-12-03 11:18:14 25 4
gpt4 key购买 nike

我不知道如何简洁地表达这个问题的标题。我发现了一些相关的问题,例如 this one ,但他们似乎都没有明确回答我的问题。
但基本上我要问的是:
考虑以下代码


static <A, B> Class<? extends A> getLeftClass(Pair<A, B> tuple) {
A left = tuple.getLeft();
return left.getClass();
}
照原样,此代码无法编译。编译失败并出现错误 Type mismatch: cannot convert from Class<capture#20-of ? extends Object> to Class<? extends A>我认为这本质上是因为 getClass返回一个类型 Class<? extends Object>但编译器期望 Class<? extends A> .
一种解决方案是按如下方式转换类:

static <A, B> Class<? extends A> getLeftClass(Pair<A, B> tuple) {
A left = tuple.getLeft();
return (Class<? extends A>) left.getClass();
}
这编译。但是,由于未经检查的类型转换而出现警告。
我的问题是,警告是否合理?有正当理由不这样做吗?或者这只是编译器无法验证它是否正确的情况,但只要 tuple.getLeft()确实是 A 的一个实例?

顺便说一句, Pair类(class)是 this one ,来自 Apache 公共(public)库

最佳答案

该警告是合理的,因为它反过来允许其他不会引起警告的不安全操作。 Class的类型参数允许您执行动态运行时强制转换和实例化,这些操作的类型安全性取决于类型参数的有效性。
换句话说,您的方法允许以下操作:

Pair<List<String>,?> p = Pair.of(new ArrayList<>(), null);

List<Integer> listOfI = new ArrayList<>(Arrays.asList(1, 2, 3));
List<String> listOfS = getLeftClass(p).cast(listOfI);
listOfS.set(1, "foo");
这种情况称为堆污染,Java 的泛型类型系统保证在无警告源代码的情况下不会发生这种情况。您会收到警告并有风险。
同样,我们可以这样做:
List<String> stringList = getLeftClass(p)
.getConstructor(Collection.class).newInstance(listOfI);
assert stringList.get(0) instanceof String;// will fail
有类似的 3rd 方库,例如XML 或 JSON 的反序列化器,在提供 Class 时具有类似的类型安全假设对象作为参数来描述假定的返回类型(或结果的组成部分)。

关于java - 在 Java 中强制转换由通用实例类型的 getClass() 返回的类是否总是安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64392040/

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