繁体   English   中英

Java类名与嵌套包名相同

[英]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.acom.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 ABCimport 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://stackoverflow.com/a/9391044/4560817

用正则表达式替换文件内的文本

来自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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM