Jak uzyskać dostęp do klas java w pakiecie domyślnym?

98

Pracuję teraz razem z innymi nad projektem Grails. Muszę napisać kilka klas Java. Ale potrzebuję dostępu do obiektu, który można przeszukiwać, utworzonego za pomocą groovy. Wygląda na to, że ten obiekt należy umieścić w domyślnym pakiecie.

Moje pytanie brzmi: czy istnieje sposób na uzyskanie dostępu do tego obiektu w pakiecie domyślnym z klasy Javy w pakiecie o określonej nazwie?

Mnementh
źródło

Odpowiedzi:

129

Nie możesz używać klas w domyślnym pakiecie z nazwanego pakietu.
( Technicznie można, jak pokazano na Sharique Abdullah za odpowiedź poprzez odbicie API, ale zajęcia z nazw bezimiennego są nie w zakresie w deklaracji importowej )

Przed J2SE 1.4 można było importować klasy z domyślnego pakietu przy użyciu następującej składni:

import Unfinished;

To już nie jest dozwolone . Zatem uzyskanie dostępu do domyślnej klasy pakietu z poziomu klasy pakietu wymaga przeniesienia domyślnej klasy pakietu do osobnego pakietu.

Jeśli masz dostęp do źródła wygenerowanego przez groovy, potrzebne jest pewne przetwarzanie końcowe, aby przenieść plik do dedykowanego pakietu i dodać tę dyrektywę "pakiet" na jego początku.


Aktualizacja 2014: błąd 6975015 , dla JDK7 i JDK8, opisuje jeszcze ostrzejszy zakaz importu z pakietu bez nazwy.

TypeNameMusi być kanoniczna nazwa typu klasy, rodzaju interfejsu, typu enum lub typu adnotacji.
Typ musi być członkiem nazwanego pakietu lub elementem członkowskim typu, którego najbardziej zewnętrznym typem obejmującym leksykalnie jest element członkowski nazwanego pakietu , lub wystąpi błąd w czasie kompilacji .


Andreas zwraca uwagę w komentarzach :

"Dlaczego [pakiet domyślny] jest na pierwszym miejscu? błąd projektu?"

Nie, to celowe.
JLS 7.4.2. Unnamed Packages mówi: „Nienazwane pakiety są dostarczane przez platformę Java SE głównie ze względu na wygodę podczas tworzenia małych lub tymczasowych aplikacji lub na początku programowania”.

VonC
źródło
7
Jak już wcześniej wyjaśniłem innym ludziom, pakiet domyślny jest obywatelem drugiej kategorii w świecie Javy. Po prostu tego nie rób. :-)
Chris Jester-Young
1
Wygląda na to, że muszę się nauczyć Groovy (w bardzo ograniczonym czasowo projekcie) lub kodować w domyślnym pakiecie. :-(
Mnementh
11
@ ChrisJester-Young, jeśli tak, to dlaczego tak jest w pierwszej kolejności? błąd projektowy?
Pacerier
Dlaczego został wycofany?
Suzan Cioc
@SuzanCioc czy masz na myśli: "dlaczego po J2SE1.4 nie możesz już uzyskać dostępu do domyślnego pakietu?"
VonC,
61

W rzeczywistości możesz.

Używając reflections API, możesz uzyskać dostęp do dowolnej dotychczasowej klasy. Przynajmniej udało mi się :)

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

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");
Holger
źródło
W przypadku Scali działa następujący kod: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
Świetna odpowiedź, +1. Ponieważ pytanie było fajne, możesz jednak użyć pisania kaczego (jak sądzę, jak Duct taping) ...Class.forName("FooBar").newInstance().fooMethod("I did it")
Bill K
7

Użyj jarjar, aby przepakować plik jar, stosując następującą zasadę:

rule * <target package name>.@1

Wszystkie klasy z domyślnego pakietu źródłowego pliku jar zostaną przeniesione do pakietu docelowego, dzięki czemu będą miały do ​​nich dostęp.

Sean
źródło
4
pokaz jak używać jarjar byłby świetny
BiGGZ
@BiGGZ: Zobacz plik README.md w repozytorium jarjar github, aby zobaczyć, jak używać jarjar z ant, gradle lub wierszem poleceń.
Lucidiot
3

Możesz używać pakietów w Groovykodzie i wszystko będzie działać dobrze.

Może to oznaczać niewielką reorganizację kodu pod grails-appi na początku trochę uciążliwą, ale w przypadku dużego projektu Grails sensowne jest organizowanie rzeczy w pakiety. Używamy standardowej konwencji nazewnictwa pakietów Java com.foo.<app>.<package>.

Posiadanie wszystkiego w domyślnym pakiecie staje się przeszkodą w integracji.

Wydaje się, że to kontrolery są jedynym artefaktem (lub artefaktem) Grailsa, który jest odporny na umieszczenie w pakiecie Java. Prawdopodobnie po prostu jeszcze tego nie rozgryzłem Convention. ;-)

Ken Gentle
źródło
0

żeby zrealizować pomysł:

Z wnętrza pakietu domyślnego można uzyskać dostęp do obiektów znajdujących się w nazwanych pakietach.

Duracell De Monaco
źródło