请考虑以下场景:
/**
* A sample interface.
*/
public interface MyInterface
{
}
/**
* First sample implementation of the above interface.
*/
public class MyClass1 implements MyInterface
{
public String toString()
{
return "[ My Class 1 ]";
}
}
/**
* Second sample implementation of the above interface.
*/
public class MyClass2 implements MyInterface
{
public String toString()
{
return "[ My Class 2 ]";
}
}
import java.util.Collection;
/**
* A service interface that declares a generic method
* returning a collection of subtype the interface defined above.
*/
public interface MyService
{
public <T> extends MyInterface<Collection<T>> myMethod();
}
import java.util.Arrays;
import java.util.Collection;
/**
* The implementation of the service interface
* that returns the generic type.
*/
public class MyServiceImpl implements MyService
{
@Override
public Collection<MyInterface> myMethod()
{
return Arrays.asList(new MyClass1(), new MyClass2());
}
}
import java.util.Collection;
/**
* Simple main class to drive the point
* I would like raise in the query below.
*/
public class MyMain
{
public static void main(String[] args)
{
MyService service = new MyServiceImpl();
Collection<MyClass1> list = service.myMethod();
// This works at runtime.
System.out.println(list);
for (MyClass1 obj : list)
{
// This throws ClassCastException at runtime.
System.out.println(obj);
}
}
}
在上面的代码中,当MyService声明涉及给定类型的特定子类型时,Java泛型实现如何允许MyServiceImpl的实现返回泛型类?
如果我添加正确的泛型类型
public class MyMain {
public static void main(String[] args) {
MyService service = new MyServiceImpl();
Collection<MyInterface> list = service.myMethod();
// This works at runtime.
System.out.println(list);
for (MyInterface obj : list) {
// This doesn't throw a ClassCastException
System.out.println(obj);
}
}
}
我得到
[[ My Class 1 ], [ My Class 2 ]]
[ My Class 1 ]
[ My Class 2 ]
我不明白你如何让你的例子在没有警告的情况下编译并触发 ClassCastException。
System.out.println(list);
这一行没问题,因为它只是为在没有泛型类型的情况下强制转换为Object
的两个元素调用方法toString()
。
for (MyClass1 obj : list)
{
// This throws ClassCastException at runtime.
System.out.println(obj);
}
但是在这里你会得到一个运行时 ClassCastException,因为你正在将列表中的MyClass2
元素强制转换为类MyClass1
,这不是MyClass2
的超类。for 循环需要遍历公共超类或接口。