简体   繁体   English

Java类名与嵌套包名相同

[英]Java class name same as the nested package name

In my Java application, I use a third-party library. 在我的Java应用程序中,我使用第三方库。

However, I found something strange, there are some nested packages, and some classes whose name may be the same as the name of the package. 但是,我发现了一些奇怪的东西,有一些嵌套包,还有一些类的名称可能与包的名称相同。

I am afraid I can not make it clear. 我恐怕无法说清楚。 Here is an example: 这是一个例子:

package

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

And there is a class named 'a' inside the 'com.xx.a'. 在'com.xx.a'中有一个名为'a'的类。

So if I want to call this class 'a'... 所以如果我想把这个班叫'a'......

I write: 我写:

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

Then the IDE will think that I mean the package 'com.xx.a.a'. 然后IDE会认为我的意思是包'com.xx.a.a'。

Then I can not call it. 然后我不能称之为。

I wonder why? 我想知道为什么?

By the way, it seems that the library provider did not want us to use these kinds of classes. 顺便说一下,图书馆提供者似乎不希望我们使用这些类。

How do they do this? 他们如何做到这一点?

The Java language allows class identifiers to be obscured by package identifiers. Java语言允许类标识符包标识符遮蔽 In your case the class com.xx.a is obscured by the package com.xx.a . 在您的情况下, com.xx.acom.xx.a com.xx.a

From the Java Language Specification : Java语言规范

6.3.2 Obscured Declarations 6.3.2模糊的声明

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type or a package . 一个简单的名称可能出现在上下文中,它可能被解释为变量,类型或包的名称 In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. 在这些情况下,§6.5的规则指定将优先选择变量而不是类型,并且将优先选择类型而不是包。 Thus, it may sometimes be impossible to refer to a visible type or package declaration via its simple name. 因此,有时可能无法通过其简单名称引用可见类型或包声明。 We say that such a declaration is obscured. 我们说这样的声明是模糊的。

I must say that the rules in §6.5 for classifying the meaning of an identifier are far from clear though. 我必须说§6.5中用于对标识符含义进行分类的规则远非明确。

The reason why you still happen to have a copy of a library that violates this rule is because the rule does not apply for class files / JAR files and the JVM. 您仍然碰巧有一个违反此规则的库副本的原因是因为该规则不适用于类文件/ JAR文件和JVM。

This means that you can have such naming conflicts in JAR files, but you'll never see it as output from javac . 这意味着您可以在JAR文件中出现此类命名冲突,但您永远不会将其视为javac输出。 The tool that has produced these class / package names is most likely a code obfuscator which produces this kind of messy code to compress the size of the files and to obfuscate the code to prevent reverse engineering. 生成这些类/包名称的工具很可能是代码混淆器 ,它产生这种混乱的代码来压缩文件的大小并混淆代码以防止逆向工程。


PS. PS。 At a closer look it may actually be a bug on the Eclipse side (assuming that's the IDE you're talking about). 仔细看看它实际上可能是Eclipse方面的一个错误(假设你正在谈论的是IDE)。 By letting an empty package name collide with a class name, Eclipse chokes on something javac accepts. 通过让空包名与类名冲突,Eclipse会对javac接受的内容进行扼杀。 The spec is hard to follow, but from what I can see, javac follows the spec in this case. 规范很难遵循,但从我所看到的,javac遵循这种情况下的规范。

This is a common issue when decompiling jars. 这是反编译jar时的常见问题。 The Compiler will get confused when there is a class and a subpackage with the same name. 当有一个类和一个具有相同名称的子包时,编译器会感到困惑。 If you don't find a compiler with the option to append a prefix regarding the type(package, class variable) you have to refactor the source files. 如果找不到带有关于类型(包,类变量)的前缀的选项的编译器,则必须重构源文件。 You can do that with regex by for example renaming every package declaration and import from import ABC to something like import pkgA.pkgB.C. 您可以使用正则表达式执行此操作,例如重命名每个包声明并从import ABCimport pkgA.pkgB.C. Of course you can't do that for the external packages from the sdk or other libraries but most of the time the used obfuscator renames them in the same way so for renaming to letters from AZ you could use something like: 当然你不能对sdk或其他库中的外部包执行此操作,但大多数情况下使用的混淆器以相同的方式重命名它们,因此要重命名为AZ中的字母,您可以使用以下内容:

RegexFindAll("import\\s+(?:[AZ]\\s*.\\s*)*([AZ])\\s*.\\s*(?:[AZ]\\s*.\\s*)*[AZ]\\s*;") RegexFindAll(“进口\\ S +(?:[AZ] \\ S * \\ S *)*([AZ])\\ S * \\ s *(。。?。[AZ] \\ S * \\ S *)* [AZ ] \\ S *;“)

RegexFindAll("package\\s+(?:([AZ])\\s*.\\s*)*([AZ])\\s*;") RegexFindAll( “?包\\ S +(:([AZ])\\ S * \\ S *)*([AZ])\\ S *;”)

And from there on you can rename every package. 从那以后,您可以重命名每个包。 If your IDE doesn't offer such functionality you can also rely on the terminal with following commands. 如果您的IDE不提供此类功能,您还可以使用以下命令来使用终端。

To find all the files by name recursively(extendable with filename filter) 按名称递归查找所有文件(可使用文件名过滤器扩展)

find -follow from https://stackoverflow.com/a/105249/4560817 https://stackoverflow.com/a/105249/4560817 find -follow

To iterate over the found filenames 迭代找到的文件名

sudo find . -name *.mp3 |
while read filename
do
    echo "$filename"    # ... or any other command using $filename
done

from https://stackoverflow.com/a/9391044/4560817 来自https://stackoverflow.com/a/9391044/4560817

To replace text inside a file with regex 用正则表达式替换文件内的文本

sed -i 's/original/new/g' file.txt from https://askubuntu.com/a/20416 来自https://askubuntu.com/a/20416的 sed -i 's/original/new/g' file.txt

You need to do this: 你需要这样做:

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

Or import the package: 或者导入包:

import com.xx.a;

a ma = new a();

The library is likely obfuscated (eg using proguard) to reduce size, prevent reverse engineering and "hide" stuff you're not supposed to use. 该库很可能被混淆(例如使用proguard)以减小尺寸,防止逆向工程并“隐藏”您不应该使用的东西。 Even if you manage to create an instance of this class, I would recommend against it, as you don't know what it will do or how it can/should be used. 即使您设法创建此类的实例,我也会建议您反对它,因为您不知道它将做什么或如何/应该使用它。

we can not do this in java: 我们不能在java中这样做:

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

the package name clashes with a class in the parent package,. 包名与父包中的类冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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