动态初始化对象
Initializing objects dynamically
以下代码为简化版。 Write
和 Read
是实现 IAction
接口的 classes。
IAction newAction;
if (userInput.equalsIgnoreCase("WRITE")){
newAction = new Write();
}
else if (userInput.equalsIgnoreCase("READ")){
newAction = new Read();
}
...
如果我要执行很多操作,那么我将不得不执行太多的 if 语句。所以问题是是否有一种方法可以自动创建每个 class 而无需通过所有这些 if 语句?
是的,有可能。首先创建一个对象。然后检查 Classname 是否存在以确保用户输入是有效的 class,然后创建动态 class。之后将其分配给您的对象。
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.
}
您稍后可以使用
检查class
if (newAction instanceOf MyClass) { }
else if (newAction instanceOf Anotherclass) {}
但是要小心。出于安全原因,不推荐这样做。您应该在执行此操作之前验证输入!
我要看你说的"automatically"是什么意思了。计算机自动做事,但在有人编程自动做事之前不会。您可能是指 "less cumbersome"。这是一种使用 Java 8 个特征的方法。
// 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();
如果您不使用 Java 8,您可以使用稍微不同(但相似)的方法:
// 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();
您可以创建枚举。
public enum Action implements IAction{
READ,WRITE;
}
并像这样在一行中使用它。
IAction action = Action.valueOf(userInput.toUpperCase());
您可以使用枚举并为每个枚举常量实现接口。这是实施 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);
}
};
}
你可以这样使用它:
Consumer<String> c = Action.valueOf("READ");
c.accept("Greetings!");
c = Action.valueOf("WRITE");
c.accept("Hello World!");
这将打印
Read: Greetings!
Write: Hello World!
可以使用String.toUpperCase()
得到正确的常量,不分大小写
以下代码为简化版。 Write
和 Read
是实现 IAction
接口的 classes。
IAction newAction;
if (userInput.equalsIgnoreCase("WRITE")){
newAction = new Write();
}
else if (userInput.equalsIgnoreCase("READ")){
newAction = new Read();
}
...
如果我要执行很多操作,那么我将不得不执行太多的 if 语句。所以问题是是否有一种方法可以自动创建每个 class 而无需通过所有这些 if 语句?
是的,有可能。首先创建一个对象。然后检查 Classname 是否存在以确保用户输入是有效的 class,然后创建动态 class。之后将其分配给您的对象。
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.
}
您稍后可以使用
检查classif (newAction instanceOf MyClass) { }
else if (newAction instanceOf Anotherclass) {}
但是要小心。出于安全原因,不推荐这样做。您应该在执行此操作之前验证输入!
我要看你说的"automatically"是什么意思了。计算机自动做事,但在有人编程自动做事之前不会。您可能是指 "less cumbersome"。这是一种使用 Java 8 个特征的方法。
// 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();
如果您不使用 Java 8,您可以使用稍微不同(但相似)的方法:
// 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();
您可以创建枚举。
public enum Action implements IAction{
READ,WRITE;
}
并像这样在一行中使用它。
IAction action = Action.valueOf(userInput.toUpperCase());
您可以使用枚举并为每个枚举常量实现接口。这是实施 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);
}
};
}
你可以这样使用它:
Consumer<String> c = Action.valueOf("READ");
c.accept("Greetings!");
c = Action.valueOf("WRITE");
c.accept("Hello World!");
这将打印
Read: Greetings!
Write: Hello World!
可以使用String.toUpperCase()
得到正确的常量,不分大小写