在Java中通过反射将元素添加到泛型列表
我试图为子类列表创建一个通用方法,无论我选择哪个子类,它都会添加一个新元素 为此,我举了一个容易理解的例子。 动物园里有一个装满长颈鹿和斑马的容器。斑马和长颈鹿都是动物。我需要创建一个“mate”方法,该方法将能够获得同基因类型的列表,即长颈鹿或斑马的列表(但不是两者都有),如果列表中有两种以上的动物,mate方法将向现有列表中添加另一种类型的动物(无需复制) 所以为了解决这个问题,我想使用反射,因为我不能在java中启动泛型类型(java中不允许使用它-不允许使用new T()。 因此,我创建了第一个元素的实例,并尝试使用在Java中通过反射将元素添加到泛型列表,java,generics,Java,Generics,我试图为子类列表创建一个通用方法,无论我选择哪个子类,它都会添加一个新元素 为此,我举了一个容易理解的例子。 动物园里有一个装满长颈鹿和斑马的容器。斑马和长颈鹿都是动物。我需要创建一个“mate”方法,该方法将能够获得同基因类型的列表,即长颈鹿或斑马的列表(但不是两者都有),如果列表中有两种以上的动物,mate方法将向现有列表中添加另一种类型的动物(无需复制) 所以为了解决这个问题,我想使用反射,因为我不能在java中启动泛型类型(java中不允许使用它-不允许使用new T()。 因此,我创建
animals.add(newAnimal)将其添加到列表中代码>。。但是,编译器对此表示不满,并出现以下错误:
Error: java: no suitable method found for add(Animal)
method java.util.Collection.add(capture#1 of ? extends Animal) is not applicable
(argument mismatch; Animal cannot be converted to capture#1 of ? extends Animal)
method java.util.List.add(capture#1 of ? extends Animal) is not applicable
(argument mismatch; Animal cannot be converted to capture#1 of ? extends Animal)
我通过在运行时再次使用反射获取add方法来解决这个问题,它正在工作(注释中的行),但是我想知道为什么编译器不允许我使用add for animal,因为我自己找不到答案
守则:
class Animal implements Comparable<Animal>{
int numLegs;
@Override
public int compareTo(Animal o) {
return this.numLegs-o.numLegs;
}
}
class Giraffe extends Animal{
int neckLength;
}
class Zebra extends Animal{
int numOfStripes;
}
class Zoo{
List<Giraffe> giraffes=new ArrayList<Giraffe>();
List<Zebra> zebras=new ArrayList<Zebra>();
public void printMostAnimals(){
for(Animal a: getMostAnimals()){
System.out.println(a);
}
}
private List<? extends Animal> getMostAnimals() {
if(giraffes.size()>zebras.size())
return giraffes;
return zebras;
}
public void mate(List<? extends Animal>animals) throws IllegalAccessException, InstantiationException {
if(animals.size()>2){
Class<?> firstAnimalInstanceClass=animals.get(0).getClass();
Animal newAnimal=(Animal)firstAnimalInstanceClass.newInstance();
animals.add(newAnimal);
// animals.getClass().getDeclaredMethod("add",Object.class).invoke(animals,newAnimal);
System.out.println("new mate was added");
return;
}
System.out.println("no mate been added");
}
}
class App{
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Zoo z=new Zoo();
z.zebras.add(new Zebra());
z.zebras.add(new Zebra());
z.zebras.add(new Zebra());
z.mate(z.zebras);
System.out.println("new zebra been added?"+(z.zebras.size()>3));
}
}
类动物{
int numLegs;
@凌驾
公共内部比较(动物o){
返回this.numLegs-o.numLegs;
}
}
长颈鹿类动物{
内领长度;
}
斑马类动物{
国际货币基金组织;
}
班级动物园{
列出长颈鹿=新的ArrayList();
List zebras=new ArrayList();
公共空白打印模板(){
对于(动物a:getMostAnimals()){
系统输出打印项次(a);
}
}
private List firstAnimalInstanceClass=animals.get(0.getClass();
Animal newAnimal=(Animal)firstAnimalInstanceClass.newInstance();
动物。添加(新动物);
//getClass().getDeclaredMethod(“add”,Object.class).invoke(animals,newAnimal);
System.out.println(“添加了新配偶”);
回来
}
System.out.println(“未添加配偶”);
}
}
类应用程序{
publicstaticvoidmain(字符串[]args)抛出instanceionException、IllegalAccessException{
动物园z=新动物园();
z、 斑马。添加(新斑马());
z、 斑马。添加(新斑马());
z、 斑马。添加(新斑马());
z、 交配(斑马);
System.out.println(“添加了新斑马?”+(z.zebras.size()>3));
}
}
谢谢,您不能在列表中添加除null
以外的任何内容,因为有人可能会写:
List<Giraffe> giraffes = new ArrayList<>();
List<? extends Animal> animals = giraffes;
animals.add(new Zebra());
for (Giraffe g : giraffes) { // but there is a Zebra in there!
g.eatLeavesFrom(tallTree); // Zebras can't do that!
}
List giraffes=new ArrayList();
列表不允许将动物“aa”添加到列表中,因为“aa”可能是斑马
当您声明List@AviadShiber,不,你不能。请给我一分钟时间更新答案,让它更清楚。谢谢,我现在明白了:)。因此,当我创建一个列表时,请尝试阅读一个名为类型擦除的主题。。但是语言的一致性。
List<Giraffe> giraffes = new ArrayList<>();
List<? extends Animal> animals = giraffes;
animals.add(new Zebra());
for (Giraffe g : giraffes) { // but there is a Zebra in there!
g.eatLeavesFrom(tallTree); // Zebras can't do that!
}
class Animal<M extends Animal<M>> {
M mate;
}
class Giraffe extends Animal<Giraffe> {}
class Zebra extends Animal<Zebra> {}
<A extends Animal<A>> void matingSeason(List<A> animals) {
A x = null;
for (A a : animals) {
if (x != null) {
a.mate = x;
x.mate = a;
x = null;
} else {
x = a;
}
}
}
((List)animals).add(newAnimal);
class AnimalList<AnimalType extends Animal> extends List<AnimalType> {
void mate() {
Class<AnimalType> firstAnimalInstanceClass = animals.get(0).getClass();
AnimalType newAnimal = (AnimalType)firstAnimalInstanceClass.newInstance();
add(newAnimal);
}
}
AnimalList<Zebra>
AnimalList<Giraffe>
AnimalList<? extends Animal> list;
list.mate();