2012-03-06 96 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),所以即使它是一个包,他也仍会尝试找到第一个变量/类型。