考虑下面的代码示例:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List list = new ArrayList<Integer>();
String response = getProducer(list).get();
}
static Producer<String> getProducer(List<Integer> list) {
return new Producer<String>();
}
}
class Producer<T> {
T get() {
return null;
}
}
用Java编译时
警告:(7,39)java:需要未经检查的转换:java。util。列表
但是,当用Java编译时
错误:(7,48)java:不兼容的类型:
java。lang.Object
无法转换为java。lang.String
显然,从
getProducer(list)
返回的类型不是Producer
奇怪的是,在调用
getProducer
方法时,可以通过以下方式避免未经检查的转换来修复此问题:
从列表更改getProducer
的参数类型
使用的Java是Oracle JDK 1.8.040
当返回值的泛型类型在方法签名中固定时,传递参数的泛型类型如何影响方法返回值的泛型类型
为什么Java和Java之间的行为会有如此向后不兼容的变化
真正的问题是;为什么你可以使用原始类型?向后兼容。如果是为了向后兼容,则假设仅应使用原始类型。
当返回值的泛型类型在方法签名中固定时,传递参数的泛型类型如何影响方法返回值的泛型类型?
方法或构造函数有两种模式中的一种。它要么是完全通用的,要么是完全原始类型的,以实现向后兼容。不存在部分原始类型和部分通用的使用模式。原始类型是选项的唯一原因是向后兼容,在这种情况下,它假设所有类型都是/曾经是原始类型。
为什么Java7和Java8之间的行为发生了如此向后不兼容的变化?
由于Java1.4不再被支持,并且已经有一段时间没有被支持了,向后兼容性参数不太成立,在当前语言中给原始类型一个位置是有意义的。
让我们看看Java语言规范:
Java
…
>
如果所选方法不是泛型方法,则:
…
Java
所选方法的结果类型确定如下:
>
否则,如果要使方法适用,必须进行未经检查的转换,则结果类型为方法声明的返回类型的擦除(§4.6)。
理解“通用方法”的含义很重要:
参考文献
如果方法声明了一个或多个类型变量(§4.4),则该方法是泛型的。
换句话说,方法
static Producer<String> getProducer(List<Integer> list)
具有泛型参数和返回类型,但不是泛型的,因为它不声明类型变量。
因此,引用的部分适用,尽管在先决条件方面有所不同,但他们同意这个特定方法调用的后果,“如果未经检查的转换是方法适用所必需的,那么结果类型是擦除...方法声明的返回类型”。
因此,旧的编译器使用返回类型Producer违反了规范
这看起来像是此处和此处报告的已知兼容性问题。
从第二个链接:
以下在JDK 7中编译并带有警告的代码将不会在JDK 8中编译:
import java.util.List;
class SampleClass {
static class Baz<T> {
public static List<Baz<Object>> sampleMethod(Baz<Object> param) {
return null;
}
}
private static void bar(Baz arg) {
Baz element = Baz.sampleMethod(arg).get(0);
}
}
在JDK 8中编译这段代码会产生以下错误:
SampleClass.java:12:错误:不兼容类型:对象无法转换为Baz
Baz element = Baz.sampleMethod(arg).get(0);
注:样本类别。java使用未经检查或不安全的操作。注意:使用-Xlint重新编译:未选中以获取详细信息。1错误
由此推导,OP的代码可以通过替换这一行来修复(右手边的类型声明让我大吃一惊——我把它看作一个类型化数组列表,但它不是):
List list = new ArrayList<Integer>();
具有
List<Integer> list = new ArrayList<Integer>();
这不会导致类型从返回类型的方法getProducer(List
再次引用第二链接:
在本例中,一个原始类型被传递给
samplemethod(Baz
问题内容: 考虑以下代码示例: 当用Java 7编译时,它只会产生预期的警告: 警告:(7,39)Java:要求进行未经检查的转换: 找到: 但是,在Java 8中进行编译时,它会为分配产生以下错误: 错误:(7,48)Java:不兼容的类型:无法转换为 因此,显然从返回的类型不是,而是被擦除(也可以通过IDE中的“提取变量”功能进行确认)。这很令人困惑,因为方法总是返回。 奇怪的是,可以通过在调
下面对getHighest()和getLowest()的调用返回Comparable类型的对象,而不是T类型的对象,这正是我们想要的。为什么,我该如何改进这段代码,使这些调用返回T(这样T的字段和方法就可用了)? 下一行生成编译器错误: 错误:找不到符号符号:方法getName()位置:接口java.lang.Comparable 我想employee.getHighest()返回一个员工(而不仅
我有一个返回泛型的函数: 所以,当我试图匹配一个函数结果时,我的问题是: 我得到一个警告:“类型模式数组[CustomerInfo到[CustomerApplication到]]中的非变量类型参数CustomerApplication-DDTO未选中,因为它已被擦除消除。” 这是否意味着在Array[]中可以得到任何类型的数组?所以我已经阅读了关于ClassTag和TypeTag的文章,但是误解了
嗨,我在泛型类型和从IDE得到的警告方面有问题。我有一个保存泛型类型值的类: 我有一个抽象类: 以及扩展它的类: IDE警告我:未经检查的重写返回类型需要未经检查的转换。我错过了什么?
问题内容: 我是从Joshua Bloch的google I / O困惑者演讲中得到的。这是代码 这个main方法会引发异常,因为它是原始类型,因此in中的所有泛型都将被删除,因此最终调用而不是。 我的问题是,即使我打电话是不是应该把它调用的方法,因为由于类型擦除,这种方法是有效的并且是类型的不是? 问题答案: 被调用的方法是在编译时定义的,而不是在运行时定义的。 如果在构造函数调用中添加参数,则
问题总结:我想传递一个带有类型参数(如