我知道Java的泛型比.Net的稍差一些。
我有一个泛型类Foo<T>
,并且我确实需要使用无参数构造函数在Foo
中实例化一个T
。如何绕过Java的限制?
发布于 2009-07-07 05:23:25
一种选择是传入Bar.class
(或您感兴趣的任何类型-以任何方式指定适当的Class<T>
引用),并将该值作为字段保留:
public class Test {
public static void main(String[] args) throws IllegalAccessException,
InstantiationException {
Generic<Bar> x = new Generic<>(Bar.class);
Bar y = x.buildOne();
}
}
public class Generic<T> {
private Class<T> clazz;
public Generic(Class<T> clazz) {
this.clazz = clazz;
}
public T buildOne() throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
}
public class Bar {
public Bar() {
System.out.println("Constructing");
}
}
另一种选择是使用“工厂”接口,然后将工厂传递给泛型类的构造函数。这更加灵活,而且您不需要担心反射异常。
发布于 2010-03-12 19:28:05
这是工厂实现,如Jon Skeet suggested
interface Factory<T> {
T factory();
}
class Araba {
//static inner class for Factory<T> implementation
public static class ArabaFactory implements Factory<Araba> {
public Araba factory() {
return new Araba();
}
}
public String toString() { return "Abubeee"; }
}
class Generic<T> {
private T var;
Generic(Factory<T> fact) {
System.out.println("Constructor with Factory<T> parameter");
var = fact.factory();
}
Generic(T var) {
System.out.println("Constructor with T parameter");
this.var = var;
}
T get() { return var; }
}
public class Main {
public static void main(String[] string) {
Generic<Araba> gen = new Generic<Araba>(new Araba.ArabaFactory());
System.out.print(gen.get());
}
}
输出:
Constructor with Factory<T> parameter
Abubeee
发布于 2009-07-07 22:25:32
这里有一种不需要显式使用构造函数参数的人为方法。你需要扩展一个参数化的抽象类。
public class Test {
public static void main(String [] args) throws Exception {
Generic g = new Generic();
g.initParameter();
}
}
import java.lang.reflect.ParameterizedType;
public abstract class GenericAbstract<T extends Foo> {
protected T parameter;
@SuppressWarnings("unchecked")
void initParameter() throws Exception, ClassNotFoundException,
InstantiationException {
// Get the class name of this instance's type.
ParameterizedType pt
= (ParameterizedType) getClass().getGenericSuperclass();
// You may need this split or not, use logging to check
String parameterClassName
= pt.getActualTypeArguments()[0].toString().split("\\s")[1];
// Instantiate the Parameter and initialize it.
parameter = (T) Class.forName(parameterClassName).newInstance();
}
}
public class Generic extends GenericAbstract<Foo> {
}
public class Foo {
public Foo() {
System.out.println("Foo constructor...");
}
}
https://stackoverflow.com/questions/1090458
复制相似问题