我今天碰到了这个,我唯一能想到的是这是Java编译器中的一个错误.下面的代码编译,但肯定看起来不正确(因为testMethod在子节点中有一个differenet签名但覆盖了父节点)并且会在运行时抛出类转换异常.
public interface TestInterface<T> {
public List<String> testMethod(); // <-- List<String>
}
public class TestClass implements TestInterface {
@Override
public List<Integer> testMethod() { // <-- List<Integer> overriding List<String>!!
return Collections.singletonList(1);
}
}
Run Code Online (Sandbox Code Playgroud)
并使用以上结构:
public void test() {
TestInterface<Boolean> test = new TestClass();
List<String> strings = test.testMethod();
for (String s : strings) {
System.out.println(s);
}
}
Run Code Online (Sandbox Code Playgroud)
所有这些编译都很好,但是如果运行它会明显抛出类别转换异常.
如果您删除<T>从TestInterface,或填充T在该行中TestClass implements TestInterface<T>,则代码将不再编译,这是有道理的.Imo <T>应该对编译没有影响,testMethod因为它不参与该方法.也许添加<T>到TestInterface导致编译器键入 - 擦除方法签名,即使T不参与这些方法......?
有谁知道这里发生了什么?
如果我有一个Stack类
class Stack<E> {}
Run Code Online (Sandbox Code Playgroud)
现在,如果我这样做:
1) Stack<Integer> s = new Stack()
2) Stack s = new Stack<Integer>()
3) Stack s = new Stack()
任何人都能解释一下这些互动(通用< - > raw)会导致什么?
主要是我的疑点是第1点.事实上,如果我这样做,那么它是不安全的,因为该堆栈可以存储除Integer之外的其他类型.是的,但是如果我有一个push方法并且尝试存储除Integer以外的值,那么编译器会阻止我...所以当我有不安全的操作时?
下一个代码
public class FilterState<T>{
Map<String, Object> getProperties(){return null;} // null for shorteness
}
....
public test(FilterState filterState){
Map<String, Object> map = filterState.getProperties();
}
Run Code Online (Sandbox Code Playgroud)
产生警告
Unchecked assignment: 'java.util.Map' to 'java.util.Map<java.lang.String, java.lang.Object>
Run Code Online (Sandbox Code Playgroud)
但是,如果我用.替换过程定义
public <T> test(IFilterState<T> filterState)
Run Code Online (Sandbox Code Playgroud)
警告消失了.我不知道类通用与地图分配有什么关系.通过通用文档快速搜索没有帮助.谁知道在哪里看,有人吗?:)