Java:引用一个类型?

时间:2012-10-10 00:14:12

标签: java oop metaprogramming

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

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 个答案:

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

这比你想象的更冗长,但是有一个优点,如果你改变了BobTypeOtherType的构造函数,编译器会发现你需要更新这段代码,而不是而不是在运行时崩溃。

答案 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更可取。