一个List然后为什么代码(下面)编译?当然MyClass2应该回归List<Integer>?
public class Main {
public static void main(final String[] args) {
MyClass myClass = new MyClass();
List list = myClass.getList();
System.out.println(list);
System.out.println(list.get(0).getClass());
MyClass2 myClass2 = new MyClass2();
List list2 = myClass2.getList();
System.out.println(list2);
System.out.println(list2.get(0).getClass());
}
public interface Int1 {
public List getList();
}
public interface Int2 extends Int1 {
@Override
public List<Integer> getList();
}
public static class MyClass implements Int2 {
@Override
public List<Integer> getList() {
return Arrays.asList(1, 2, 3);
}
}
public static class MyClass2 implements Int2 {
@Override
public List getList() {
return Arrays.asList("One", "Two", "Three");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到如果你试图使它成为一个List<String>然后你得到一个错误"java:Main.MyClass2不是抽象的并且不会覆盖Main.Int2中的抽象方法getList()".我不太明白为什么你在上面的例子中没有得到这个.
注意:我的项目中的问题的解决方案是使接口本身通用,即Int1<X>(当然我使用比这更好的名称,它只是一个例子).
我怀疑,编译器应该为您提供Unchecked转换的警告,而不是将其标记为编译器错误.让我们理解为什么它会警告你:
您有以下两种方法来实现以满足您实现的接口的合同:
public List getList();
public List<Integer> getList();
Run Code Online (Sandbox Code Playgroud)
现在,如果在您的类中,您只提供第一个方法的实现,它可以处理第二个方法的请求.您可以返回a List<Integer>返回类型List.那是因为a List<Integer>只是List在运行时,由于类型擦除.
但是,如果你只是给第二个方法实现,它将不满足第一个方法的合同.第一种方法说,它可以返回任何类型List,因为它在返回类型中使用了原始类型.因此,它可以返回List<Integer>,List<Object>,List<String>,任何东西.但第二种方法只能返回List<Integer>.
编译器会在编译时执行此类型检查,它会向您发出警告,List需要进行未经检查的转换List<Integer>,因为由于类型擦除,转换无论如何都会在运行时成功.
这是类似的情况如下:
List<String> listString = new ArrayList<String>();
List rawList = new ArrayList();
listString = rawList; // Warning: Unchecked conversion
rawList = listString;
Run Code Online (Sandbox Code Playgroud)
推荐阅读:
给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则而没有发生编译时错误,则从S到T存在转换转换.
如果S是类类型:
Run Code Online (Sandbox Code Playgroud)If T is a class type, then either |S| <: |T|, or |T| <: |S|. Otherwise, a compile-time error occurs. Furthermore, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types(§4.5),并且X和Y的擦除相同,发生编译时错误.
在你的情况下List<Integer>,List<String>可证明是不同的参数化类型,它们都有相同的删除:List.