Как получить доступ к java-классам в пакете по умолчанию?

98

Сейчас я работаю вместе с другими над проектом Grails. Мне нужно написать несколько Java-классов. Но мне нужен доступ к объекту с возможностью поиска, созданному с помощью groovy. Похоже, что этот объект нужно поместить в default-package.

Мой вопрос: есть ли способ получить доступ к этому объекту в пакете по умолчанию из класса Java в названном пакете?

Mnementh
источник

Ответы:

129

Вы не можете использовать классы в пакете по умолчанию из именованного пакета.
( Технически вы можете, как показано на Sharique Абдулла ответа через Reflection API, но классы от безымянного пространства имен находятся не в объеме в декларации импорта )

До J2SE 1.4 вы могли импортировать классы из пакета по умолчанию, используя такой синтаксис:

import Unfinished;

Это больше не разрешено . Таким образом, для доступа к классу пакета по умолчанию из упакованного класса необходимо переместить класс пакета по умолчанию в собственный пакет.

Если у вас есть доступ к источнику, сгенерированному Groovy, потребуется некоторая пост-обработка, чтобы переместить файл в специальный пакет и добавить эту директиву «package» в его начало.


Обновление 2014: ошибка 6975015 , для JDK7 и JDK8, описывает еще более строгий запрет на импорт из безымянного пакета.

TypeNameДолжно быть каноническое имя типа класса, тип интерфейса, перечислимого типа, или типа аннотаций.
Тип должен быть либо членом именованного пакета , либо членом типа, самый внешний лексически включающий тип которого является членом именованного пакета , в противном случае возникает ошибка времени компиляции .


Андреас отмечает в комментариях :

"почему [пакет по умолчанию] там вообще? ошибка дизайна?"

Нет, это умышленно.
JLS 7.4.2. Безымянный пакет говорит: «Безымянный пакет предоставляется платформой Java SE в основном для удобства при разработке небольших или временных приложений или когда только начинается разработка».

VonC
источник
7
Как я уже объяснял другим людям, пакет по умолчанию - это гражданин второго сорта в мире Java. Просто не делай этого. :-)
Chris Jester-Young
1
Кажется, мне нужно изучить Groovy (в проекте с очень ограниченным временем) или код в пакете по умолчанию. :-(
Mnementh
11
@ ChrisJester-Young, если да, то почему он вообще там? ошибка дизайна?
Pacerier
Почему он устарел?
Suzan Cioc
@SuzanCioc, вы имеете в виду: "почему после J2SE1.4 вы больше не можете получить доступ к пакету по умолчанию?"
VonC
61

Фактически, вы можете.

Используя API отражений, вы можете получить доступ к любому классу на данный момент. По крайней мере, мне удалось :)

Class fooClass = Class.forName("FooBar");
Method fooMethod = fooClass.getMethod("fooMethod", String.class);

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");
Хольгер
источник
Для Scala работает следующий код:val bar = "hi"; val fooClass = Class.forName("FooClass"); val fooMethod = fooClass.getMethod("foo", classOf[Array[String]]); val fooReturned = fooMethod.invoke(fooClass.newInstance(), Array(bar));
Jus12,
2
Отличный ответ, +1. Однако, поскольку вопрос был отличным, вы можете использовать утиную печать (я думаю, как пленку из воздуховода) ...Class.forName("FooBar").newInstance().fooMethod("I did it")
Bill K
7

Используйте jarjar, чтобы переупаковать файл jar по следующему правилу:

rule * <target package name>.@1

Все классы в пакете по умолчанию исходного файла jar будут перемещены в целевой пакет, таким образом, они смогут получить доступ.

Шон
источник
4
демо того, как использовать jarjar, было бы здорово
BiGGZ 02
@BiGGZ: см. Файл README.md в репозитории jarjar на github, чтобы узнать, как использовать jarjar с ant, gradle или командной строкой.
Lucidiot
3

Вы можете использовать пакеты в Groovyкоде, и все будет работать нормально.

Это может означать небольшую реорганизацию кода grails-appи поначалу небольшую боль, но в большом проекте Grails просто имеет смысл организовать вещи в пакетах. Мы используем стандартное соглашение об именах пакетов Java com.foo.<app>.<package>.

Как вы обнаружите, наличие всего в пакете по умолчанию становится препятствием для интеграции.

Контроллеры кажутся единственным артефактом (или артефактом) Grails, который сопротивляется помещению в пакет Java. Наверное, я просто еще не понял, в Conventionчем дело. ;-)

Кен Джентл
источник
0

просто для завершения идеи:

Изнутри default-package вы можете получить доступ к объектам, находящимся в названных пакетах.

Ява
источник