今天早些时候,我认为您希望 List<? extends AbstractInst<? extends IInstType>> 成为 insts 的数据类型。它肯定是一种与您正在创建的对象匹配的数据类型,但我怀疑在这种情况下它是否真的是您想要的。一个解释是为了。
假设您有一个类扩展了另一个类,例如PrintWriter 扩展Writer。也就是说,每个PrintWriter 也是一个Writer,但还有一些额外的方法(如println)可以用PrintWriter 类型的变量调用,但不能用Writer 类型的变量调用。 (比起标准的Dog extends Animal,我更喜欢真实的例子)。
了解ArrayList<PrintWriter> 不是ArrayList<Writer> 的子类型很重要,尽管直观上看起来可能是这样。原因是这样的。假设我有一个变量myList,我写myList.add(new StringWriter());myList 可以是什么类型?它显然不能是ArrayList<PrintWriter> 类型,因为StringWriter 不是PrintWriter。但它可以是ArrayList<Writer> 类型,因为StringWriter 肯定是Writer,因此必须能够添加到ArrayList<Writer>。
因此,任何ArrayList<Writer> 在行中都可以正常工作
myList.add(new StringWriter());
但任何ArrayList<PrintWriter> 都不会。因此,ArrayList<PrintWriter> 不可能是 ArrayList<Writer> 的特殊类型,就像 PrintWriter 是 Writer 的特殊类型一样。
换一种说法,应该可以这样写
ArrayList<Writer> myList = new ArrayList<Writer>();
myList.add(new StringWriter());
然而编译器应该以某种方式阻止我们写这个
ArrayList<Writer> myList = new ArrayList<PrintWriter>();
myList.add(new StringWriter());
既然第二行明显OK,那肯定是第一行产生了编译错误。确实如此 - 您不能将 ArrayList<PrintWriter> 分配给 ArrayList<Writer> 类型的变量,因为 ArrayList<PrintWriter> 只是 不是 ArrayList<Writer>。或者正如 Jon Skeet 在 https://stackoverflow.com/a/2745301/1081110 上所说的那样,“Awooga awooga”。
尽管如此,ArrayList<Writer>、ArrayList<PrintWriter> 和 ArrayList<StringWriter> 在某种程度上看起来有点相似。似乎应该有某种类型的变量可以引用这三个中的任何一个。确实有 - 它是ArrayList<? extends Writer>。但这是一个抽象类型。你不能实例化它。你不能写new ArrayList<? extends Writer>()——最终ArrayList<? extends Writer>实际上必须是ArrayList<Writer>、ArrayList<PrintWriter>或ArrayList<StringWriter>(或者可能是ArrayList或其他类型的Writer)。
这对我们来说应该不会太令人不安。毕竟List<Writer>也是一个抽象类型。你不能写new List<Writer>(),因为List<Writer>实际上必须是ArrayList<Writer>,或LinkedList<Writer>,或其他类型的Writer列表。
此外,ArrayList<? extends Writer> 类型的变量并不总是最有用的变量,因为您不能使用它向列表中添加内容。如果myList 是ArrayList<? extends Writer> 类型,那么无论myWriter 是什么类型都不能写myList.add(myWriter);,因为编译器无法检查myWriter 是不是正确的 /em> 类似于Writer 的列表。
你可以用ArrayList<? extends Writer> 类型的变量做的就是把事情从列表中取出。如果myList 是ArrayList<? extends Writer> 类型,那么你可以写
Writer myWriter = myList.get(0);
因为无论myList 是指ArrayList<Writer>、ArrayList<PrintWriter> 还是ArrayList<StringWriter>,你都知道其中的内容是某种Writer。
所以回到实际的问题,你在哪里
List<AbstractInst<? extends IInstType>> insts = new ArrayList<MIPSInst>();
这最初似乎是合理的,因为正如您所解释的,MIPSInst 确实是AbstractInst<? extends IInstType> 的子类型。或者换句话说,每个MIPSInst 都是一个AbstractInst<? extends IInstType>。
显然,你可以写
List<MIPSInst> insts = new ArrayList<MIPSInst>();
并且能够将事物添加到列表中,并将事物从列表中取出。但是您想使用某种类型表达式来表明任何类型的 AbstractInst<? extends IInstType> 都可以,并且您只会将此变量用于适用于任何类型的 List 或 AbstractInst<? extends IInstType> 对象的东西。
正如我在StringWriter / PrintWriter 示例中所展示的,您要查找的类型是List<? extends AbstractInst<? extends IInstType>>。这封装了这个列表可以是任何类型的AbstractInst<? extends IInstType> 的List,包括MIPSInst。
但是,除非您将此变量转换为其他变量,否则使用此类型会将您限制为列表的只读视图。你可以get列表中的东西,但你不能add任何东西,因为编译器无法检查你是否添加了正确的AbstractInst<? extends IInstType>。
在这个特定的实例中,您正在创建一个空列表。所以引用它可能不是很有用,它可以让你get 东西,但不是add 东西。因此,与我之前的评论相反,您最好将变量声明为 List<MIPSInst>,然后将 add 和 get 声明为您心中的内容。