2012-03-06 102 views
2

在我的Java應用程序中,我使用了第三方庫。Java類名與嵌套包名相同

但是,我發現一些奇怪的東西,有一些嵌套的軟件包,以及一些其名稱可能與軟件包名稱相同的類。

恐怕我不能說清楚。這裏有一個例子:

com.xx.a 
    com.xx.a.a 

而且有一個名爲 'A' 的 'com.xx.a' 內部類。

所以,如果我想調用這個類 'A' ...

我寫:

a ma = new com.xx.a.a(); 

然後IDE會認爲我說的是包「com.xx.a.a 」。

然後我不能調用它。

我想知道爲什麼?

順便說一下,似乎庫提供者不希望我們使用這些類。

他們如何做到這一點?

回答

5

Java語言允許通過包標識符將類標識符變爲模糊。在您的情況下,類別com.xx.a包裹com.xx.a遮蓋。

Java Language Specification

6.3.2遮住聲明

在那裏它可以潛在地被解釋爲一個可變,類型或一個的名稱的上下文,可能會出現一個簡單的名稱包。在這些情況下,§6.5的規則指定將優先於類型選擇變量,並且將優先選擇類型作爲包。因此,它有時可能是不可能通過其簡單名稱引用可見類型或包裝聲明。 我們說這樣的聲明是模糊的。

我必須說,在§6.5中對標識符的含義進行分類的規則並不明確。

您之所以仍然碰巧擁有違反此規則的庫副本,是因爲該規則不適用於類文件/ JAR文件和JVM。

這意味着你在可以在JAR文件中有這樣的命名衝突,但是你永遠不會將它看作javac的輸出。產生這些類/包名稱的工具很可能是代碼混淆器,它會產生這種混亂的代碼來壓縮文件的大小並混淆代碼以防止逆向工程。


PS。仔細一看,它可能實際上是Eclipse端的一個錯誤(假設這是您正在討論的IDE)。通過讓一個空的包名與一個類名相沖突,Eclipse上的扼制器就可以接受javac。規範很難遵循,但從我所看到的,javac遵循這種情況下的規範。

+0

這是否意味着模糊處理是在類文件而不是.java源代碼上完成的? – hguser 2012-03-06 13:12:50

+0

是的,如果他們使用標準的Java編譯器,那就是它的意思。 – aioobe 2012-03-06 13:14:47

0

你需要這樣做:

com.xx.a.a ma = new com.xx.a.a(); 

或進口包裝:

import com.xx.a; 

a ma = new a(); 
0

該庫有可能混淆(例如使用ProGuard),以減少大小,防止逆向工程和「隱藏」你不應該使用的東西。即使你設法創建了這個類的一個實例,我也會推薦它,因爲你不知道它會做什麼或者如何使用它。與父包中的類

com.xx.A 
com.xx.A.yy 

包名稱衝突,.:

+0

即使代碼被混淆了,但我想知道它爲什麼可以工作?正如simaremare所說,我們不能在java中這樣做,所以我想知道是否在生成的類文件上進行了混淆處理? – hguser 2012-03-06 13:05:29

+0

使用proguard時,對類文件進行模糊處理。 – claesv 2012-03-06 13:25:40

0

有時你想訪問包而不是類。 但編譯器的順序是變量類型包。 我不得不重命名所有的包,類和變量。

例如: INT一個將成爲INT a_var 類一個將成爲類a_class 包封裝的將成爲a_package

我用蝕重構功能這一點。

您仍然需要通過類,並通過追加_var,_class或_package來重命名所有衝突。努力工作,但由於Eclipse無法通過使用知道(String a.a.b.c,import a.b.c.d),所以即使它是一個包,他也仍會嘗試找到第一個變量/類型。