[英]Java class name same as the nested package name
在我的Java應用程序中,我使用第三方庫。
但是,我發現了一些奇怪的東西,有一些嵌套包,還有一些類的名稱可能與包的名稱相同。
我恐怕無法說清楚。 這是一個例子:
包
com.xx.a
com.xx.a.a
在'com.xx.a'中有一個名為'a'的類。
所以如果我想把這個班叫'a'......
我寫:
a ma = new com.xx.a.a();
然后IDE會認為我的意思是包'com.xx.a.a'。
然后我不能稱之為。
我想知道為什么?
順便說一下,圖書館提供者似乎不希望我們使用這些類。
他們如何做到這一點?
Java語言允許類標識符被包標識符遮蔽 。 在您的情況下, 類 com.xx.a
被com.xx.a
包 com.xx.a
。
從Java語言規范 :
6.3.2模糊的聲明
一個簡單的名稱可能出現在上下文中,它可能被解釋為變量,類型或包的名稱 。 在這些情況下,§6.5的規則指定將優先選擇變量而不是類型,並且將優先選擇類型而不是包。 因此,有時可能無法通過其簡單名稱引用可見類型或包聲明。 我們說這樣的聲明是模糊的。
我必須說§6.5中用於對標識符含義進行分類的規則遠非明確。
您仍然碰巧有一個違反此規則的庫副本的原因是因為該規則不適用於類文件/ JAR文件和JVM。
這意味着您可以在JAR文件中出現此類命名沖突,但您永遠不會將其視為javac
輸出。 生成這些類/包名稱的工具很可能是代碼混淆器 ,它產生這種混亂的代碼來壓縮文件的大小並混淆代碼以防止逆向工程。
PS。 仔細看看它實際上可能是Eclipse方面的一個錯誤(假設你正在談論的是IDE)。 通過讓空包名與類名沖突,Eclipse會對javac接受的內容進行扼殺。 規范很難遵循,但從我所看到的,javac遵循這種情況下的規范。
這是反編譯jar時的常見問題。 當有一個類和一個具有相同名稱的子包時,編譯器會感到困惑。 如果找不到帶有關於類型(包,類變量)的前綴的選項的編譯器,則必須重構源文件。 您可以使用正則表達式執行此操作,例如重命名每個包聲明並從import ABC
到import pkgA.pkgB.C.
當然你不能對sdk或其他庫中的外部包執行此操作,但大多數情況下使用的混淆器以相同的方式重命名它們,因此要重命名為AZ中的字母,您可以使用以下內容:
RegexFindAll(“進口\\ S +(?:[AZ] \\ S * \\ S *)*([AZ])\\ S * \\ s *(。。?。[AZ] \\ S * \\ S *)* [AZ ] \\ S *;“)
RegexFindAll( “?包\\ S +(:([AZ])\\ S * \\ S *)*([AZ])\\ S *;”)
從那以后,您可以重命名每個包。 如果您的IDE不提供此類功能,您還可以使用以下命令來使用終端。
按名稱遞歸查找所有文件(可使用文件名過濾器擴展)
從https://stackoverflow.com/a/105249/4560817
find -follow
迭代找到的文件名
sudo find . -name *.mp3 |
while read filename
do
echo "$filename" # ... or any other command using $filename
done
用正則表達式替換文件內的文本
來自https://askubuntu.com/a/20416的
sed -i 's/original/new/g' file.txt
你需要這樣做:
com.xx.a.a ma = new com.xx.a.a();
或者導入包:
import com.xx.a;
a ma = new a();
該庫很可能被混淆(例如使用proguard)以減小尺寸,防止逆向工程並“隱藏”您不應該使用的東西。 即使您設法創建此類的實例,我也會建議您反對它,因為您不知道它將做什么或如何/應該使用它。
我們不能在java中這樣做:
com.xx.A
com.xx.A.yy
包名與父包中的類沖突。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.