tony
tony

Reputation: 1651

Initializing objects dynamically

The following code is a simplified version. The Write and Read are classes that implement the IAction interface.

IAction newAction;
if (userInput.equalsIgnoreCase("WRITE")){
    newAction = new Write();
}
else if (userInput.equalsIgnoreCase("READ")){
    newAction = new Read();
}
...

If I had many actions to implement then i would have to go through too many if statements. So the question is if there is a way to automatically create each class without getting through all these if statements?

Upvotes: 1

Views: 1254

Answers (4)

fabian
fabian

Reputation: 82461

You can use a enum and implement the interface for each enum constant. Here's an example for implementing Consumer<String>:

public enum Action implements java.util.function.Consumer<String> {
    READ {
        @Override
        public void accept(String t) {
            System.out.println("Read: "+t);
        }
    },
    WRITE {
        @Override
        public void accept(String t) {
            System.out.println("Write: "+t);
        }
    };
}

You can use it like this:

Consumer<String> c = Action.valueOf("READ");
c.accept("Greetings!");
c = Action.valueOf("WRITE");
c.accept("Hello World!");

This will print

Read: Greetings!
Write: Hello World!

You can use String.toUpperCase() get the right constant regardless of upper and lower case.

Upvotes: 0

jax
jax

Reputation: 38633

You can create an enum.

public enum Action implements IAction{
    READ,WRITE;
}

And use it in one line like so.

IAction action = Action.valueOf(userInput.toUpperCase());

Upvotes: 1

Jesper
Jesper

Reputation: 206896

I depends on what you mean by "automatically". Computers do things automatically, but not before someone programmed to do something automatically. You probably mean "less cumbersome". Here is an approach that uses Java 8 features.

// Make a Map that tells what word should be coupled to what action
Map<String, Supplier<IAction>> actionMapping = new HashMap<>();
actionMapping.put("WRITE", Write::new);
actionMapping.put("READ", Read::new);

// When you get user input, simply lookup the supplier
// in the map and call get() on it
IAction action = actionMapping.get(userInput.toUpperCase()).get();

If you're not using Java 8, you can use a slightly different (but similar) approach:

// Map that tells what word should be coupled to what action
Map<String, Class<? extends IAction>> actionMapping = new HashMap<>();
actionMapping.put("WRITE", Write.class);
actionMapping.put("READ", Read.class);

// Lookup the action class for the input and instantiate it
IAction action = actionMapping.get(userInput.toUpperCase()).newInstance();

Upvotes: 2

Emanuel
Emanuel

Reputation: 8106

Yes, its possible. First create an Object. Then check if the Classname exists to make sure that the userinput is a valid class, then create a dynamic class. After that assign it to your Object.

Object newAction = null;

 try {
  Class<?> clazz =  Class.forName( "your.fqdn.class."+userInput );
  Constructor<?> ctor = clazz.getConstructor(String.class);
  newAction = ctor.newInstance(new Object[] { ctorArgument });
  newAction = new your.fqdn.class."+userInput;
 } catch( ClassNotFoundException e ) {
   // catch an error if the class for the object does not exists.
}

You can later check for the class by using

if (newAction instanceOf MyClass) { } 
else if (newAction instanceOf Anotherclass) {}

But be carefull. This is for security reasons not recommend. You should validate the input before you do that!

Upvotes: 2

Related Questions