我正在将一些C#代码移植到Java上。我遇到了Syntax的问题,特别是new()。我理解在哪里类似于Java的泛型:T扩展了FOO。
如何在Java中复制new()参数?
即:
public class BAR<T> : BAR
where T : FOO, new()
以下是我实施cletus解决方案的方法:
public class BAR<T extends FOO> extends ABSTRACTBAR {
public BAR(T t) throws InstantiationException, IllegalAccessException{
t.getClass().newInstance();
this.value = t;
}
}
答案 0 :(得分:7)
你不能在Java中复制它,因为泛型在C#和Java之间根本不同。 Java使用类型擦除,因此泛型类型参数不会(大部分)在运行时保留。如果你想构造泛型类型参数的元素,那么你需要传入一个类实例:
public class Bar<T extends Foo> {
private final Class<T> clazz;
public class Bar(Class<T> clazz) {
this.clazz = clazz;
}
public T newInstance() {
return clazz.newInstance(); // this will throw checked exceptions
}
}
编辑:只是为了解决泛型类型参数的运行时类型安全问题:显然,由于类型擦除,Java不会本机拥有它:没有运行时泛型类型参数的类型。但是有一个解决方案。您使用Collections.checkedList()
:
List<String> list = Collections.checkedList(new ArrayList<String>(),
String.class);
如果您尝试插入非String
的内容,此集合现在会抛出异常。
答案 1 :(得分:0)
你做不到。 Java使用擦除实现泛型类型安全,并且不支持基于构造函数签名的类型,因此无法完全执行此操作并进行静态类型检查。
答案 2 :(得分:0)
希望这会有所帮助。请注意,这需要在创建新实例的时候出现一个无参数构造函数。
public class TypeStuff {
private static final long serialVersionUID = 1L;
// *** PUBLIC STATIC VOID MAIN ***
public static void main(String[] args) {
TypeStuff ts = new TypeStuff();
ts.run();
}
// *** CONSTRUCTOR ***
public TypeStuff () {
}
public void run() {
Fruit banana = new Banana();
Fruit dupe = newT(banana);
System.out.println("dupe.getColor()=" + dupe.getColor());
Fruit orange = new Orange();
Fruit dupe2 = newT(orange);
System.out.println("dupe2.getColor()=" + dupe2.getColor());
}
public <T extends Fruit> T newT(T fruit) {
T dupe = null;
try {
Class clazz = fruit.getClass();
dupe = (T) clazz.newInstance();
} catch (Exception ex) {
} finally {
return dupe;
}
}
interface Fruit {
String getColor();
}
static class Banana implements Fruit {
public Banana() {
}
@Override
public String getColor() {
return "Yellow";
}
}
static class Orange implements Fruit {
public Orange() {
}
@Override
public String getColor() {
return "Orange";
}
}
} // CLOSE CLASS.