如何从泛型方法

时间:2018-05-29 06:24:35

标签: java generics

我正在尝试用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)方法通用?

3 个答案:

答案 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中出现语法错误。使用反射来创建一个实例,这个重构在编译时会被忽视,并会在运行时引发异常。