Имя класса Java совпадает с именем вложенного пакета - PullRequest
3 голосов
/ 06 марта 2012

В моем Java-приложении я использую стороннюю библиотеку.

Однако я обнаружил что-то странное, есть несколько вложенных пакетов и некоторые классы, чье имя может совпадать с именем пакета.

Боюсь, я не могу это прояснить.Вот пример:

package

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

И внутри класса com.xx.a есть класс с именем 'a'.

Так что если я хочучтобы называть этот класс 'a' ...

Я пишу:

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

Тогда в среде IDE будет думать, что я имею в виду пакет 'com.xx.a.a'.

Тогда я не могу это назвать.

Интересно, почему?

Кстати, похоже, что поставщик библиотеки не хотел, чтобы мы использовали такие классы.

Как они это делают?

Ответы [ 5 ]

5 голосов
/ 06 марта 2012

Язык Java позволяет идентификаторам классов быть скрытыми идентификаторами пакетов. В вашем случае класс com.xx.a скрыт пакетом com.xx.a.

Из Спецификации языка Java :

6.3.2 Скрытые декларации

Простое имя может встречаться в контекстах, где оно может потенциально интерпретироваться как имя переменной, типа или пакета . В этих ситуациях правила §6.5 указывают, что переменная будет выбрана в предпочтении к типу, и что тип будет выбран в предпочтении к пакету. Таким образом, иногда невозможно сослаться на видимый тип или объявление пакета через его простое имя. Мы говорим, что такая декларация скрыта.

Я должен сказать, что правила в п. 6.5 для классификации значения идентификатора далеко не ясны.

Причина, по которой у вас все еще есть копия библиотеки, которая нарушает это правило, заключается в том, что правило не применяется к файлам классов / JAR-файлам и JVM.

Это означает, что вы можете иметь такие конфликты именования в файлах JAR, но вы никогда не увидите его как вывод javac. Инструментом, который создал эти имена классов / пакетов, скорее всего, является кодовый обфускатор , который создает этот вид грязного кода для сжатия размера файлов и обфускации кода для предотвращения обратного инжиниринга.


PS. При ближайшем рассмотрении это может быть ошибка на стороне Eclipse (при условии, что вы говорите об IDE). Позволяя пустому имени пакета вступать в противоречие с именем класса, Eclipse захлебывается тем, что принимает javac. Трудно следовать спецификации, но из того, что я вижу, javac следует спецификации в этом случае.

0 голосов
/ 05 октября 2017

Это распространенная проблема при декомпиляции jar-файлов.Компилятор будет сбит с толку, когда есть класс и подпакет с тем же именем.Если вы не найдете компилятор с опцией добавления префикса, относящегося к типу (пакет, переменная класса), вам необходимо провести рефакторинг исходных файлов.Вы можете сделать это с помощью regex, например, переименовав каждое объявление пакета и импортировав из import A.B.C в нечто вроде import pkgA.pkgB.C. Конечно, вы не можете сделать это для внешних пакетов из sdk или других библиотек, но большую часть времени используютсяobfuscator переименовывает их таким же образом, поэтому для переименования в буквы из AZ вы можете использовать что-то вроде:

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

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

И с этого момента вы можете переименовать каждый пакет.Если ваша IDE не предлагает такую ​​функциональность, вы также можете положиться на терминал с помощью следующих команд:

Чтобы найти все файлы по имени рекурсивно (расширяется с помощью фильтра имен файлов)

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

Для перебора найденных имен файлов

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

из https://stackoverflow.com/a/9391044/4560817

Заменить текст внутри файла регулярным выражением

sed -i 's/original/new/g' file.txt из https://askubuntu.com/a/20416

0 голосов
/ 06 марта 2012

Библиотека, вероятно, запутана (например, использует proguard), чтобы уменьшить размер, предотвратить реверс-инжиниринг и «спрятать» вещи, которые вы не должны использовать.Даже если вам удастся создать экземпляр этого класса, я бы порекомендовал против этого, поскольку вы не знаете, что он будет делать или как его можно / нужно использовать.

0 голосов
/ 06 марта 2012

мы не можем сделать это в Java:

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

имя пакета конфликтует с классом в родительском пакете.

0 голосов
/ 06 марта 2012

Вам нужно сделать это:

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

Или импортируйте пакет:

import com.xx.a;

a ma = new a();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...