考虑以下代码示例:
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编译时,它只会产生预期的警告getProducer(list)
:
警告:(7,39)Java:要求进行未经检查的转换:
java.util.List<java.lang.Integer>
找到:
java.util.List
但是,在Java 8中进行编译时,它会为response = getProducer(list).get()
分配产生以下错误:
错误:(7,48)Java:不兼容的类型:
java.lang.Object
无法转换为java.lang.String
因此,显然从返回的类型getProducer(list)
不是Producer<String>
,而是被擦除Producer
(也可以通过IDE中的“提取变量”功能进行确认)。这很令人困惑,因为getProducer
方法总是返回Producer<String>
。
奇怪的是,可以通过在调用getProducer
方法时避免未经检查的转换来解决此问题,方法是:
getProducer
从更改List<Integer>
为List
list
变量类型从更改List
为List<Integer>
这看起来像是在此处和此处报告的已知兼容性问题。
从第二个链接:
以下在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);
注意:SampleClass.java使用未经检查或不安全的操作。注意:使用-Xlint:unchecked重新编译以获取详细信息。1个错误
因此,可以通过替换此行来固定OP的代码(右侧的类型声明使我失望-我将其视为不是类型化数组列表的形式阅读):
List list = new ArrayList<Integer>();
与
List<Integer> list = new ArrayList<Integer>();
这不会导致类型从方法的返回类型中删除 getProducer(List<Integer> list)
再次引用第二个链接:
在此示例中,将原始类型传递给
sampleMethod(Baz<Object>)
可通过子类型化应用的 方法(请参见JLS,Java SE 7
Edition,第15.12.2.2节)。要应用该方法,必须进行未经检查的转换,因此将删除其返回类型(请参见JLS,Java SE 7
Edition,第15.12.2.6节)。在此情况下的返回类型sampleMethod(Baz<Object>)
是
java.util.List
代替java.util.List<Baz<Object>>
并因此返回类型get(int)
是Object
,这是不分配兼容Baz
。
考虑下面的代码示例: 用Java编译时 警告:(7,39)java:需要未经检查的转换:
嗨,我在泛型类型和从IDE得到的警告方面有问题。我有一个保存泛型类型值的类: 我有一个抽象类: 以及扩展它的类: IDE警告我:未经检查的重写返回类型需要未经检查的转换。我错过了什么?
下面对getHighest()和getLowest()的调用返回Comparable类型的对象,而不是T类型的对象,这正是我们想要的。为什么,我该如何改进这段代码,使这些调用返回T(这样T的字段和方法就可用了)? 下一行生成编译器错误: 错误:找不到符号符号:方法getName()位置:接口java.lang.Comparable 我想employee.getHighest()返回一个员工(而不仅
我正在堆栈中实现一个列表链接。该程序成功通过了所有必需的测试,但我遇到了此警告。程序的实现没有中断,但我正在寻求消除此问题。你能告诉我如何通过编辑Equals方法中的代码来修复它吗?未选中的强制转换:“java.lang.对象”到“LinkedStack”
问题内容: 考虑以下代码: 如果我用以下命令编译它: 它返回: 请注意,即使在返回类型上未引用任何泛型类型,也仅将泛型方法视为不安全。 这是一个错误吗?还是有一个更深层次的原因我没有考虑? 问题答案: 允许使用原始类型以确保与引入泛型之前编写的代码兼容。原始类型的工作原理是,仅从所有方法参数和返回类型中忽略 所有 类型信息,甚至与该类的类型参数无关的类型信息。正如您所发现的,这可能导致奇怪的结果。
我大致了解什么是类型擦除以及为什么我们会遇到未经检查的警告。但是,我不明白为什么在以下情况下只发出一个未经检查的警告: 不幸的是,两个接听电话都与大小写子句匹配。编译器确实为第一个子句发出了警告: 警告:未检查类型模式列表[Double]中的非可变类型参数Double,因为它已被擦除消除。 我知道TypeTag[T]可以用来实现更好的类型安全。但是我在这里关心的是为什么没有针对第二个case子句发