为什么整个包结构需要包含在Class.forName()中?

时间:2016-03-04 12:38:46

标签: java

我开发了一个普通的Java项目,我试图理解ClassNotFoundExceptionNoClassDefFoundException之间的区别。我发现了一个奇怪的行为,当我调用Class.forName()时,我需要包含整个包结构。

请参阅以下代码:

package org.com;

public class MainApp {

    public static void main(String[] args) {
        try {
             Class cls = Class.forName("org.com.MainApp");
             System.out.println("Class = " + cls.getName());
         } catch(ClassNotFoundException ex) {
             System.out.println(ex.toString());
         }
    }

}

如果我使用Class.forName("MainApp")代替Class.forName("org.com.MainApp"),则会抛出异常。

有人可以解释一下这个的实际原因吗?

5 个答案:

答案 0 :(得分:7)

基本上,因为the contract says so

  

className - 所需类的完全限定名称。

你可以在不同的包中有两个名为MainApp的类。如果省略完全限定名称(即包括包),类加载器将如何知道要加载哪个类?

换句话说,这是一个设计决定,在我看来,是一个好的。

Class.forName("MainApp")实际上会尝试加载位于默认包中的名为MainApp的类,即该类中未指定包名。

答案 1 :(得分:5)

因为您的类存在于该包中,而forName方法需要完全限定名称

假设java有一个AI来通过仅指定名称来识别你的类,当你指定“Date”时会发生什么?

Class cls = Class.forName("Date");

是否需要为您提供java.util. Date课程或java.sql.Date课程或任何第三方资料库日期课程?

这就是为什么你需要指定包名来唯一标识该类

答案 2 :(得分:2)

Class.forName没有关于你的类的任何概念或它的调用位置。

这是一个通用工具。

例如:

你是这个名叫亚历山大的城市中唯一的人。 您通过亚马逊订购包裹,然后将其交付给亚历山大。

从你的角度来看,你是这个城市唯一的亚历山大人,很容易吗?

现在从亚马逊的角度来看......他们不知道在哪里发送它。

同样的逻辑适用于class.forName。

答案 3 :(得分:1)

当你编译代码时,编译器知道你正在编译哪个包以及你导入了哪些类,所以当你给它一个类名时,它可以检查这些东西以找到你想要的完全限定的类名。

但是,Class.forName是类Class上的方法。它只知道你传递了什么,类名。它不知道调用者的包,也不知道您使用的是什么。只有完全限定的类名才能工作。

答案 4 :(得分:1)

简单回答:

同一个类可能是多个包的一部分,而JVM不确定要加载哪个类。

MainApppackage1可能有package2个课程。

为避免含糊不清,Class.forName

需要完全限定的班级名称

e.g。

Class.forName("package1.MainApp") 
Class.forName("package2.MainApp") 

来自documentation页面的说明:

public static Class<?> forName(String className)
                        throws ClassNotFoundException
  

返回与具有给定字符串名称的类或接口关联的Class对象。调用此方法相当于:   Class.forName(className,true,currentLoader)

参数:

className - 所需类的完全限定名称。

  

返回:具有指定名称的类的Class对象。