我正在尝试用Java学习泛型。我的问题是我可以从泛型方法实例化一个java类吗?我有一个像下面这样的方法
private void AddAction(ModelBuilding model,TableView table) {
table.getItems().add( new ModelBuilding());
}
这里ModelBuilding()
是我的自定义java类。当我试图使这个方法通用时,我在实例化ModelBuilding()
类时面临问题。我尝试过这样做并遇到编译错误。
private <E> void AddAction(E mode,TableView table) {
table.getItems().add( new E());
}
如何使AddAction(E mode,TableView table)
方法通用?
答案 0 :(得分:1)
由于您将E
的实例传递给您的方法,因此您可以通过反射创建同一个类的实例:
private <E> void AddAction(E mode,TableView table) {
table.getItems().add(mode.getClass().newInstance());
}
另一方面,如果您没有使用传递给方法的E
实例,那么它足以传递Class<E>
以创建新实例:
private <E> void AddAction(Class<E> clazz,TableView table) {
table.getItems().add(clazz.newInstance());
}
无论哪种方式,您都必须捕获newInstance()
可能引发的一些异常。
或者,只需添加传递给方法的实例即可。该方法的调用者将创建实例:
private <E> void AddAction(E mode,TableView table) {
table.getItems().add(mode);
}
答案 1 :(得分:0)
你试过这个吗?
private <E> void AddAction(E mode,TableView table)
{
table.getItems().add( mode);
}
答案 2 :(得分:0)
正如Eran所提到的,使用反射来创建实例可以触发异常。 javadoc说:
请注意,此方法会传播由nullary抛出的任何异常 构造函数,包括已检查的异常
因此,在使用newInstance()
时,您不会在编译时发现任何可能的异常。
此外,您只能使用“nullary constructor”。如果要创建没有默认构造函数的操作或想要使用参数化构造函数,则必须在java.lang.reflect.Constuctor
上使用反射调用。在代码重构方面,这一切都非常脆弱。
关于重构的至少更安全的方法是使用工厂方法。您可以传入Class<E> clazz
,而不是将Supplier<E>
传递给您的方法。看看下面的代码:
private <E> void AddAction(Supplier<E> factory, TableView table) {
E mode = factory.get();
table.getItems().add(mode);
}
private void AddSimpleAction(TableView table) {
AddAction(SimpleAction::new, table);
}
private void AddDateAwareAction(TableView table) {
AddAction(() -> new DateAwareAction(new Date()), table);
}
private static class SimpleAction {
// body
}
private static class DateAwareAction {
private final Date date;
public DateAwareAction(Date date) {
this.date = date;
}
// body
}
如果重构DateAwareAction
的构造函数以使用参数long dateTimeInMs
,则会在方法AddDateAwareAction
中出现语法错误。使用反射来创建一个实例,这个重构在编译时会被忽视,并会在运行时引发异常。