使用forName()动态调用Class时的ClassNotFoundException

时间:2014-07-24 07:43:36

标签: java eclipse class dynamic

我试图在eclipse中动态调用特定的类,特别是MyClass0

完全限定类路径存储在String array[]中,其中索引与许多MyClass中的一个相关联(MyClass0,MyClass1 ... MyClass-nth)。

每个MyClass都有相同的方法和数据结构,但值不同。

package forName;

public class Main {

    private static String toMyClassOf_ID[];

    public static void main(String[] args) {
        toMyClassOf_ID = new String[1]; //new String[n];
        toMyClassOf_ID[0] = ("/exampleForName/src/forName/MyClass0.java"); //toClass[ MyClass_ID ]
    /*  .
     *  .
     *  toClass[n] = ...
     */ 
        Class toMyClass;

        try {
            Class cls = Class.forName(toMyClassOf_ID[0]);
            ClassLoader clsLoader = cls.getClassLoader();
            toMyClass= Class.forName(toMyClassOf_ID[0], true, clsLoader);
        } 
        catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //toMyClass.doMethod(); //commeted to allow run test
    }
}

// ----------

package forName;

public class MyClass0 {

    public static void doMethod() {
        System.out.println("success");
    }
}

问题:

  • 我正在"java.lang.ClassNotFoundException"

问题:

  • forName()是正确的做法吗?
  • 我是否正确使用完全合格的类路径toMyClassOf_ID[0],以实现此目的?例如("/exampleForName/src/forName/MyClass0.java"
  • 如果没有使用的正确格式,我该如何找到它?

5 个答案:

答案 0 :(得分:0)

除了可怕的命名等,这是错误的:

"/exampleForName/src/forName/MyClass0.java"

你需要:

"forName.MyClass0"

答案 1 :(得分:0)

Class.forName不是等待文件的路径,而是等待完整的类名(即不带.java扩展名的包+类名):forName.MyClass0

答案 2 :(得分:0)

没有权利指定.java文件的路径

您的java文件的.class文件应该使用Class.forName

参考http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)

答案 3 :(得分:0)

您必须将FQCN(完全限定类名称)作为参数传递给forName,而是指定.java文件的路径不正确。

更改以下行

toMyClassOf_ID[0] = ("/exampleForName/src/forName/MyClass0.java");

必须更改为 -

toMyClassOf_ID[0] = "forName.MyClass0"; //Fully Qualified Class Name in java package notation

答案 4 :(得分:0)

如前所述

Class.forName()

接受类的完全限定名称,该名称是包声明中给出的包的名称,在您的情况下" forName",后跟一个点后跟类的名称给定在类声明中,在您的情况下" MyClass0"。 所以工作示例将是

Class<?> cls = Class.forName("forName.MyClass0");

您不能像尝试那样使用源文件的路径。

但是在阅读时

  

每个MyClass都有相同的方法和数据结构,但值不同。

我不确定这是不是你应该或想要做的。

听起来你最好有一个班级&#34; MyClass&#34;使用实例方法和实例字段以及预定义实例列表。

如果您要执行此操作,则可以静态初始化这些实例:

public MyClass {
  public static final MyClass[] instances;
  static {
    instances = new MyClass[1];
    instances[0] = new MyClass();
    instances[0].myField = "value1";
  }

  private String myField;
  public void doMethod()
  {
    ...
  }
}

当然,您可以使用其他机制来创建这些实例,例如工厂方法或依赖注入。

你说每个MyClass都有不同的值。如果你还需要每个MyClass都有不同的doMethod(或任何其他方法)实现,你应该使用MyClass作为基类,并实现从MyClass扩展的子类。

public class MyClass0 extends MyClass
{
  @Override
  public void doMethod()
  {
    // different implementation
  }
}

您可以再次使用静态初始化:

public class MyClass
{
  public static final MyClass[] instances;
  static {
    instances = new MyClass[1];
    instances[0] = new MyClass0();
    instances[0].myField = "value1";
  }
  ...
}

当然现在你有从基类到子类的依赖,这通常不是一个好主意,但我认为这是你问题的直接解决方案。