ArrayList<Class<? extends Interface1>>
到
ArrayList<Class<?>>
因为第二个显然是第一个限制较少的版本。但是,以下代码无法编译:
import java.util.ArrayList;
public class TypeInvocationConversionTest
{
private static ArrayList<Class<? extends Interface1>> classList;
private static ArrayList<Class<?>> lessRestrictiveClassList;
public static void main(String[] args)
{
classList = new ArrayList<Class<? extends Interface1>>();
lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
}
private interface Interface1 {}
}
但产生错误
TypeInvocationConversionTest.java:12: inconvertible types
found : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList<java.lang.Class<?>>
lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
^
我不认为想要转换这两种类型是不合理的:为了激励,这里有一个与我实际处理的更接近的简短程序(此代码无法编译):
import java.util.ArrayList;
public class Mammal
{
public void produceMilk() {}
}
public class Reptile
{
public void layEggs() {}
}
public interface Species
{
String getSpeciesName();
}
public class Dog extends Mammal
implements Species
{
@Override
public String getSpeciesName()
{
return "Canis lupus familiaris";
}
}
public class Cat extends Mammal
implements Species
{
@Override
public String getSpeciesName()
{
return "Feles catus";
}
}
public class Boa extends Reptile
implements Species
{
@Override
public String getSpeciesName()
{
return "Boa constrictor";
}
}
public class Panel3 extends Reptile
implements Species
{
@Override
public String getSpeciesName()
{
return "Dromiceiomimus brevitertius";
}
}
public class AnimalFunTime
{
public static void main(String[] args)
{
ArrayList<Class<? extends Mammal>> listOfMammals;
ArrayList<Class<? extends Reptile>> listOfReptiles;
ArrayList<ArrayList<Class<?>>> matrixOfAnimals;
listOfMammals.add(Dog.class);
listOfMammals.add(Cat.class);
listOfReptiles.add(Boa.class);
listOfReptiles.add(Panel3.class);
///////////////////////////////////////////////////////////////////////////
// The following two lines cause an error. //
///////////////////////////////////////////////////////////////////////////
matrixOfAnimals.add( (ArrayList<Class<?>>) listOfMammals);
matrixOfAnimals.add( (ArrayList<Class<?>>) listOfReptiles);
// Get milk.
for (int i = 0 ; i < listOfMammals.size() ; i++) {
listOfMammals.get(i).produceMilk();
}
// Get eggs.
for (int i = 0 ; i < listOfReptiles.size() ; i++) {
listOfReptiles.get(i).layEggs();
}
// Display all the animals' names.
for (int j = 0 ; j < matrixOfAnimals.size() ; j++) {
ArrayList<Class<?>> currentFamily = matrixOfAnimals.get(j);
for (int i = 0 ; i < currentFamily.size() ; i++) {
Class<?> currentAnimal = currentFamily.get(i);
if (Species.isAssignableFrom(currentAnimal) {
System.out.println(currentAnimal.getSpeciesName());
}
else
{
throw new SpeciesNotImplementedException("Please tell us the animal's name!");
}
}
}
}
}
正如评论所说,此代码无法编译,因为我无法创建包含ArrayList<Class<? extends Mammal>>
和ArrayList<Class<? extends reptile>>
对象的列表。如果我可以将它们都转换为ArrayList<Class<?>>
s,那就没关系了。有没有办法进行演员表这样的事情有效吗?
答案 0 :(得分:5)
这不会(也不应该)起作用的原因之一是lessRestrictiveClassList
会引用与classList
相同的列表对象。因此,如果您将Class<?>
类型的对象(其中?
未扩展Interface1
)添加到该列表中,则classList
的合同突然被破坏:
ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();
// assume this is allowed:
ArrayList<Class<?>> lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
// now add an element to the less restrictive list
lessRestrictiveClassList.add(String.class);
// and obtain it from the original list
// this code will crash, because String does not implement Interface1
Class<? extends Interface1> cls = classList.get(0);
最后一行会遇到大问题,因为它可能会导致意外的代码失败。
您应该复制到限制较少的列表,而不是两次引用数组列表:
ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();
ArrayList<Class<?>> lessRestrictiveClassList = new ArrayList<>();
lessRestrictiveClassList.addAll(classList);
答案 1 :(得分:3)
忘记泛型并转换为原始类型ArrayList。
ArrayList<ArrayList> matrixOfAnimals = new ArrayList<>();
matrixOfAnimals.add(listOfMammals);
答案 2 :(得分:3)
因为第二个显然是第一个限制较少的版本。
不是。即使List<A>
是List<B>
的子类型,A
也不是B
的子类型。 Heuster说明了为什么它不安全。
如果您不需要使用第二个列表引用添加元素,则应使用ArrayList<? extends Class<?>>
。您可以将ArrayList<Class<? extends Interface1>>
转换为该内容。
答案 3 :(得分:2)
你可以通过连续两次演员来完成你想要的演员表:
lessRestrictiveClassList = (ArrayList<Class<?>>) (ArrayList<?>) classList;
编译。