简体   繁体   English

java.lang.ClassNotFoundException:一个

[英]java.lang.ClassNotFoundException: A

I was testing an example of accessing private method from another class and got an exception 我正在测试一个从另一个类访问私有方法的示例,但出现异常

public class WithoutMain 
{       
    public static void main(String args[]) throws Exception
    {
        Class c = Class.forName("A");
        Object o = c.newInstance();
        Method m = c.getDeclaredMethod("message", null);
        m.setAccessible(true);
        m.invoke(o, null);
    }
}

public class A {

    private void message(){ 
        System.out.println("This is a private method.");
    }
}

Getting following exception 获取以下异常

Exception in thread "main" java.lang.ClassNotFoundException: A
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)

These 2 class resides in same package. 这两个类位于同一包中。 Can anyone tell me why this exception shows? 谁能告诉我为什么显示此异常?

You need to use the fully qualified name of a class to load it using Class.forName() 您需要使用类的全限定名来使用Class.forName()加载它

Now you may argue why? 现在您可能会争论为什么? As in your case both the classes are in the same directory/package. 与您的情况一样,这两个类都在同一目录/包中。

I would argue the other way, there is no rule defined in java that the class loader will look in the same directory first. 我会反过来说,在Java中没有定义规则,该类加载器将首先在同一目录中查找。

If you want to learn how class loading works, I would suggest you source code for the class java.lang.ClassLoader class 如果您想了解类加载的工作方式,建议您使用java.lang.ClassLoader类的源代码。

So when you invoke the Class.forName it uses delegation and the class loader which is assigned the job to load this class will not know the current package or any location. 因此,当您调用Class.forName它将使用委托,并且被分配了用于加载此类的作业的类加载器将不知道当前包或任何位置。 Hence, it needs the fully qualified class name. 因此,它需要完全限定的类名。

One more tip, in java a fully qualified class name of a loaded class is <ClassLoader><packageName><className> . 还有一个技巧,在Java中,已加载类的完全限定类名是<ClassLoader><packageName><className> This is how the classes in JVM are uniquely identified. 这就是唯一标识JVM中的类的方式。

Hope this helps 希望这可以帮助

EDIT 编辑

Your code will work only in one condition and that is, if both the classes are in default package. 您的代码只能在一种情况下工作,也就是说,如果两个类都在默认程序包中。

您必须提供类的完全限定名称,而不仅仅是简单的类名称。

Class c = Class.forName("<package>.A");

Try changing 尝试改变

    Class c = Class.forName("A");

to

    Class c = Class.forName("yourPackagePath.A");

the forName method does not take in account the package of the user call. forName方法不考虑用户调用的程序包。

You need the FQN as per the docs : 您需要按照文档提供 FQN:

Parameters: 参数:
className - the fully qualified name of the desired class. className-所需类的完全限定名称。

The Java Class class isn't in your package, so it needs to know where the class is located otherwise it doesn't know where it is in order to load it(just like the classloader loads it from a full file path). Java Class类不在您的程序包中,因此它需要知道该类的位置,否则就不知道要将该类加载到何处(就像类加载器是从完整文件路径加载它一样)。

so 所以

Class<? extends Object> c = Class.forName("A");

needs to be 需要是

Class<? extends Object> c = Class.forName("package.A");

where package is the full qualified name of the package so if the package is 其中package是软件包的全限定名称,因此如果package是

foo.bar

it would become 它会变成

Class<? extends Object> c = Class.forName("foo.bar.A");

As already stated in answers before, needs full name. 如之前的答案中所述,需要全名。

To avoid manually typing it you can simply use: 为了避免手动输入,您可以简单地使用:

Class<?> clazz = Class.forName(A.class.getName());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM