我有一个超类,其泛型类型扩展了超类型(<E extends ...>
)。该类有一个抽象方法,返回泛型类型的列表
我还有一些实现抽象方法的子类
当我调用此方法并尝试替换列表中的对象时,java编译器显示错误。我认为错误是因为我的转换函数返回了一个不同的类型捕获,因为它作为参数得到
以下是使用Exception作为通用超类型的示例代码:
import java.util.ArrayList;
import java.util.List;
public class GenericTest {
abstract class Super<E extends Exception>{
abstract List<E> foo();
}
class Sub1 extends Super<NullPointerException>{
@Override
List<NullPointerException> foo(){
return new ArrayList<NullPointerException>();
}
}
GenericTest(Super<? extends Exception> s){
List<? extends Exception> list = s.foo();
list.set(0, convertException(list.get(0)));
}
static <F extends Exception> F convertException(F exception){...}
}
行
list.set(0, convertException(list.get(0)));
编译器说set
:
The method set(int, capture#2-of ? extends Exception) in the type List<capture#2-of ? extends Exception> is not applicable for the arguments (int, capture#3-of ? extends Exception)
和convertException
:
Type mismatch: cannot convert from capture#3-of ? extends Exception to capture#2-of ? extends Exception
为什么不转换EException会返回相同的capture#x
?它需要F并返回F.
感谢您的帮助!
答案 0 :(得分:3)
这是因为您将Super作为原始类型传递给构造函数。您没有使用通用。由于您未指定泛型类型,因此编译器会将该列表视为Object列表。
应该是这样的:
GenericTest(Super<Exception> s){
Exception e = s.foo().get(0);
}
这将编译好
<强>更新强>
编译器对set
说类型List中的方法set(int,capture#2-of?extends Exception)不适用于参数(int,capture#3-of?extends Exception)
当您使用通配符时,Java不允许您添加或更新Collection的元素。所以,使用:
List<? extends Exception> list = s.foo();
list.set(0, /*anything but null*/);
是被禁止的。 原因是为了避免这种情况:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public void method() {
List<Dog> dogs = new ArrayList<Dog>();
addCats(dogs);
}
void addCats(List<? extends Animal> list) {
list.add(new Cat());
}
你明白了吗?如果允许添加操作,则可能会将猫添加到狗列表中。
回到你的问题。我不明白你要做什么,如果你真的需要一个具有特定子类异常的列表,我建议你也把GenericTest作为泛型类。否则,您可以将列表声明为Exception的简单列表:
GenericTest(Super<Exception> s){
List<Exception> list = s.foo();
list.set(0, convertException(list.get(0)));
}
然后对列表元素进行instanceof检查。
希望这有帮助
更新2
为什么convertException不知道,它会返回与列表相同的类型?
问题不在于编译器不知道“F扩展Exception ==?extends Exception”。这段代码:
GenericTest(Super<Exception> s){
List<? extends Exception> list = getList();
}
<F extends Exception> List<F> getList(){...}
将编译。问题是你在带有通配符的集合上使用set方法,这是禁止的,无论你实际传递的是什么对象。
答案 1 :(得分:1)
你可以使用施法。 Object是一个超类https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html
Exception e = (Exception) s.foo().get(0);
我认为这是你的目标?
List<NullPointerException> ds = new GenericTest.Sub1().foo();
Exception e2 = ds.get(0);