简体   繁体   中英

how do I Instantiating a java class from generic method

I am trying to learn generics in Java. My question is can i instantiating a java class from generic method? I have a method like below

private  void  AddAction(ModelBuilding model,TableView table) {         
            table.getItems().add( new ModelBuilding());
        }

Here ModelBuilding() is my custom java class. When I am trying to make this method generic I am facing problem in instantiating ModelBuilding() class. I tried like this and having a compile error.

private <E> void  AddAction(E mode,TableView table) {           
            table.getItems().add( new E());
        }

How I can make AddAction(E mode,TableView table) method generic?

Since you are passing an instance of E to your method, you can create an instance of the same class via reflection:

private <E> void AddAction(E mode,TableView table) {           
    table.getItems().add(mode.getClass().newInstance());
}

On the other hand, if you are not using the E instance passed to your method, it's enough to pass a Class<E> in order to create a new instance:

private <E> void AddAction(Class<E> clazz,TableView table) {           
    table.getItems().add(clazz.newInstance());
}

Either way, you'll have to catch some exceptions that may be thrown by newInstance() .

Or, just add the instance passed to your method. The caller of the method will create the instance:

private <E> void AddAction(E mode,TableView table) {           
    table.getItems().add(mode);
}

Did you try this

    private <E> void AddAction(E mode,TableView table)
    {           
       table.getItems().add( mode);
    }

As Eran mentioned using reflection to create an instance can trigger exceptions. The javadoc says:

Note that this method propagates any exception thrown by the nullary constructor, including a checked exception

So when using newInstance() you aren't aware of any possible exceptions at compile time.

Furthermore you are limited to use the "nullary constructor". If you want to create an action which has no default constructor or want to use a parametrized constructor you would have to use a reflection call on a java.lang.reflect.Constuctor . This all is very fragile regarding code refactoring.

An at least safer approach regarding refactoring is to use a factory method. Instead of passing Class<E> clazz to your method, you could pass in for example a Supplier<E> . Take a look at the following code:

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
}

If you refactor the constructor of DateAwareAction to use a parameter long dateTimeInMs you get a syntax error in the method AddDateAwareAction . Using reflection to create an instnace this refactoring would stay unnoticed at compile time and would raise an exception at runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM