我需要根据条件实例化两种不同类型之一的对象。两种类型的构造函数都使用相同的参数,两者都是主类型的子类。我可以在条件内定义对正确类型的引用,然后使用该引用实例化对象吗?快速举例:
if (v == "bob") {
Object myType = bobType;
} else {
Object myType = otherType;
}
SuperType instance = new myType(arg1, arg2);
这不起作用;在java中是否有正确的语法?这是执行此操作的快捷方式:
if (v == "bob") {
SuperType instance = new bobType(arg1, arg2);
} else {
SuperType instance = new otherType(arg1, arg2);
}
我实际上制作了几个相同类型的实例,它们都需要很长的参数列表,我想避免重复自己,除了类型。
答案 0 :(得分:3)
您可以,但必须使用Reflection API。有什么理由你不能这样写:
SuperType instance;
if (v == "bob") {
instance = new bobType(arg1, arg2);
} else {
instance = new otherType(arg1, arg2);
}
否则你想要的是使用Class类型来获取对构造函数的引用,然后你可以直接调用构造函数:
SuperType instance;
Class<? extends SuperType> clazz;
Constructor<? extends SuperType> constructor;
if ("bob".equals(v)) {
clazz = bobType.class;
} else {
clazz = otherType.class;
}
//subbing in types of arg1 and arg2 of course
constructor = class.getConstructor(String.class, String.class);
instance = constructor.newInstance(arg1, arg2);
因此,如果您的目标只是简洁,那么它的冗长程度并不会那么冗长,而且反射会抛出您需要处理的各种已检查异常。如果您在编译时知道所有可能的类型,那么没有太大的优势。如果您不了解所有类型并且正在按名称查找其他库中的类,那么它将非常有用。
答案 1 :(得分:2)
可以使用反射,但在大多数情况下,定义工厂更为惯用。例如,
interface MyFactory {
SuperType newInstance(Foo arg1, Bar arg2);
}
class BobFactory implements MyFactory {
public BobType newInstance(Foo arg1, Bar arg2) {
return new BobType(arg1, arg2);
}
}
class OtherFactory implements MyFactory {
public OtherType newInstance(Foo arg1, Bar arg2) {
return new OtherType(arg1, arg2);
}
}
void myMethod() {
MyFactory factory;
if (v == "bob") {
factory = new BobFactory();
} else {
factory = new OtherFactory();
}
SuperType instance = factory.newInstance(arg1, arg2);
}
这比你想象的更冗长,但是有一个优点,如果你改变了BobType
或OtherType
的构造函数,编译器会发现你需要更新这段代码,而不是而不是在运行时崩溃。
答案 2 :(得分:1)
在java中有点复杂,你需要使用classname创建一个实例。看看这个问题:Creating an instance using the class name and calling constructor
答案 3 :(得分:0)
您的代码:
if (v == "bob") {
Object myType = bobType;
} else {
Object myType = otherType;
}
SuperType instance = new myType(arg1, arg2);
根据条件,我理解你想要的是实例化不同的类型。
您可以选择声明变量以使其范围超出if-else条件(最好,我们称之为选项#1)并创建工厂构造函数以便您实例化正确的类型(不太可能需要) ,似乎是一种矫枉过正的选择#2)。
选项#1:
简单地宣布声明:
// declare "instance" so it exists inside if-else AND after condition
SuperType instance;
if (v == "bob") {
// instantiate "instance"
instance = new bobType(arg1, arg2);
} else {
// instantiate "instance"
instance = new otherType(arg1, arg2);
}
// "instance" is now instantiated
选项#2:
背景: http://en.wikipedia.org/wiki/Factory_method_pattern
基本上你要做的是创建一个接口来构造SuperType类型。显然,两个类(bobType和otherType)都应该实现它 - 这样你就可以立即实例化对象。这并不能解除您在代码中访问“工厂”的可能性,如果它不是重复操作,则选项#1更可取。