我有这样的方法 -
public List<Apples> returnFruits(String arg1){
List<Apples> fruits = new ArrayList<Apples>();
Apple a = new Apple();
fruits.add(a);
return fruits;
}
我想更改它,以便我可以从方法调用中指定水果类型并返回该水果列表。所以第二个语句应该动态实例化我传递的水果列表。我想到了这个 -
public List<?> returnFruits(String arg1){
List<T> fruits = new ArrayList<T>();
T t = new T();
fruits.add(t);
return fruits;
}
但是你可以看到,不知道正确的方法。
在第二种方法中,我只返回水果而不是列表 -
public T returnFruit(){
T t = new T();
return t;
}
传递的果实不在同一个类层次结构中,并且是不同的类型。
谢谢。
答案 0 :(得分:6)
如果您确定您将拥有无参数构造函数,则可以使用以下语法:
public <T> List<T> returnFruits(Class<T> clazz){
List<T> fruits = new ArrayList<T>();
T t = clazz.newInstance();
fruits.add(t);
return fruits;
}
用法:
List<MyClass> m = returnFruits(MyClass.class, "plop");
如果您知道有一个带String参数的构造函数:
public <T> List<T> returnFruits(Class<T> clazz, String arg1){
List<T> fruits = new ArrayList<T>();
Constructor<T> constructor = clazz.getConstructor(String.class);
T t = constructor.newInstance(arg1);
fruits.add(t);
return fruits;
}
用法:
List<MyClass> m = returnFruits(MyClass.class, "plop");
等
答案 1 :(得分:4)
您可以采取多种方法。一种是使用Class<T>
,正如其他人所建议的那样。另一种方法是创建某种生成器接口,并将其传递给:
public interface FruitProducer<T> {
T createFruit(String arg);
}
public <T> List<T> returnFruits(String arg, FruitProducer<? extends T> producer) {
List<T> list = new ArrayList<T>();
T fruit = producer.createFruit(arg);
list.add(fruit);
return list;
}
你有不同水果的不同生产者:AppleProducer implements FruitProducer<Apple>
,OrangeProducer implements FruitProducer<Orange>
等。这种方法只是踢了一点 - FruitProducer
仍然需要以某种方式创造果实 - 但它可能是一个有用的重构。
另一种方法依赖于与FruitProducer
方法相同的多态性,方法是使用returnFruits
抽象类:
public abstract class FruitLister<T> {
public abstract List<T> returnFruits(String arg);
}
现在你有不同的lister:AppleLister implements FruitLister<Apple>
等。每个人都知道如何实例化它需要在列表中返回的特定类:
public class AppleLister implements FruitLister<Apple> {
@Override
public List<Apple> returnFruits(String arg) {
List<Apple> list = new ArrayList<Apple>();
Apple apple = new Apple(arg);
list.add(apple);
return list;
}
}
答案 2 :(得分:2)
Java通过擦除实现泛型,因此在运行时没有传递您传入的泛型类型的概念。也不可能new
泛型类型,因为您不能保证传入的类型将具有无参数构造函数。
您可以将类本身作为一个真实参数传递:
public <T> List<T> returnFruits(String arg1, Class<T> clazz){
...但是你需要使用反射来实例化该类的新版本,并且只需要指责用户不要提供没有默认构造函数的类。
答案 3 :(得分:0)
<T> public List<T> returnFruit(){
Apple a = new Apple();
List<Apple> list = new ArrayList<Apple>;
list.add(a);
return list;
}
应该有效。基本上,声明在方法之前需要一个类型为“T”的列表。然后,您可以返回任何类型“T”的列表。基本上,你不能做“新T()”,因为它没有任何类型信息。它必须是一个混凝土类。
如果需要,您甚至可以将该类类型作为参数传递。