Java Reflection:使用接口初始化对象,但使用字符串值作为类名

时间:2018-06-27 20:43:22

标签: java inheritance reflection interface abstraction

让我们说我有以下设置

一个interface

public interface TestInterface {

  public void draw();
}

和两个实现

public class Square implements TestInterface {

  @Override
  public void draw() {
    System.out.println("Square");

  }

}

public class Circle implements TestInterface {

  @Override
  public void draw() {
    System.out.println("Circle");

  }

}

现在我可以轻松做到

TestInterface a = new Square();
a.draw();

我正确地得到了Square。接下来,我想尝试反射。

Class<?> clazz = null;
    try {
      clazz = Class.forName(className);
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    Constructor<?> constructor = null;
    try {
      constructor = clazz.getConstructor();
    } catch (NoSuchMethodException | SecurityException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }
    Object instance = null;
    try {
      instance = constructor.newInstance();
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
        | InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    Method method = null;
    try {
      method = instance.getClass().getMethod(methodName);
    } catch (NoSuchMethodException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
      method.invoke(instance);
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

,对于classNamesome.package.SquaremethodNamedraw,我再次得到Square。哪个是对的。

问题是我的应用程序有权访问interface,但不能访问实际的实现。因此,我知道要调用的方法,但是我也必须指定已实现的类,而且我也不知道它们可能驻留在哪个包中。如果我仅知道类名而不知道包怎么办?

有没有办法我仍然可以使用

的初始化形式
TestInterface a = new <some_parameter>();
a.draw();

有没有一种概括的方法?还是我上面显示的使用反射的方法是实现类似目标的唯一方法?最后,如果我使用抽象类而不是接口,会有所不同吗?

2 个答案:

答案 0 :(得分:1)

您需要通过:

@param      className   the fully qualified name of the desired class.

例如,当您有三个同名但包装不同的班级

--package1
----Test
--package2
----Test
Main
Test

在Main中,您有:

public static void main(String[] args) throws UnsupportedEncodingException {

        Class<?> clazz = null;
        try {
            clazz = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

它将称其为Main级。要呼叫其他人,您需要传递完全合格的名字。

    clazz = Class.forName("package1.Test");
    clazz = Class.forName("package2.Test");

如果我仅知道类的名称而不知道程序包怎么办??因此,您需要知道所需的级别。因为您知道不同的包,所以类可以具有相同的名称。因此,如果遇到该问题,您需要哪个班级。

答案 1 :(得分:0)

您必须知道课程的全名。仅该类的名称不足以将其加载到内存中并通过反射使用它。但是,您可以使用reflections库来确定接口的实现。

也许这个讨论线程可以为您提供帮助:How can I get a list of all the implementations of an interface programmatically in Java?