2016-03-04 63 views
3

我开发了一个普通的Java项目,我试图了解ClassNotFoundExceptionNoClassDefFoundException之间的区别。我发现了一个奇怪的行为,那就是当我打电话给Class.forName()时,我需要包含整个包结构。为什么整个包结构需要包含在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")抛出一个异常。

有人能解释一下这个的真正原因吗?

回答

7

基本上,因为the contract says so

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

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

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

Class.forName("MainApp")实际上会尝试加载一个名为MainApp地处默认包类,那就是在类指定包名。

5

因为你的类在包中存在和的forName方法需要完全合格的名称

假设如果Java有一个AI通过指定唯一名称来标识自己的类,将在您指定的“日期” happend什么?

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

是否需要给你java.util. Date类或java.sql.Date类或任何第三方库Date类?

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

+0

感谢您的回复。我试图从一个在线学习网站获得这个想法,并且他们没有使用完全合格的名称来使用它。 – Saurabh

+0

@Saurabh他们可能会将他们的类放在默认包中。 – Pragnani

1

Class.forName没有什么概念你的类或它的调用方式。

这是一个通用的工具。

例如:

你是唯一在这个城市叫亚历山大的人。 您通过亚马逊订购包装并说,将其交付给亚历山大。

从你的角度来看,你只有一个亚历山大在城市,很容易没有?

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

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

1

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

但是,Class.forName是类Class上的方法。它所知道的是你通过它的类名。它不知道调用者的包,也不知道你使用的是什么进口。只有完全合格的类名可以使用。

0

答案很简单:

同一个类可以是多个软件包的一部分,JVM是不知道你是要加载的类。

您可能有MainApp课程package1package2

为了避免歧义,完全合格的类名称是必需的Class.forName

例如从documentation

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

注:

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

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

参数:

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

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

相关问题