2016-03-04 68 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對象。

相關問題