1

我需要根据条件实例化两种不同类型之一的对象。两种类型的构造函数都采用相同的参数,并且都是主类型的子类。我可以在条件内定义对正确类型的引用,然后使用该引用实例化对象吗?快速示例:

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);
}

我实际上正在制作几个实例,它们都是相同类型的,它们都需要一长串参数,并且我想避免完全重复自己,除了类型。

4

4 回答 4

3

可以,但必须使用反射 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);

因此,如果您的目标只是简洁,那么它并没有那么冗长,而且反射会引发您需要处理的各种检查异常。如果您在编译时知道所有可能的类型,那么实际上并没有太大的优势。如果您不知道所有类型并且正在按名称从其他库中查找类,它会变得很有用。

于 2012-10-10T00:17:14.173 回答
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);
}

这比你想象的更冗长,但它的好处是,如果你改变BobTypeor的构造函数OtherType,编译器会捕捉到你需要更新这段代码,而不是在运行时崩溃。

于 2012-10-10T00:23:34.500 回答
1

在java中它有点复杂,你需要使用类名创建一个实例。看看这个问题:使用类名和调用构造函数创建实例

于 2012-10-10T00:17:35.963 回答
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 更可取。

于 2012-10-10T00:34:22.250 回答