2015-05-15 13 views
7

Zastanawiam się, czy byłoby możliwe wygenerowanie klasy, za pośrednictwem procesora adnotacji, która byłaby wewnętrzną klasą klasy do kompilacji. Na przykład podczas kompilowania klasy A wygeneruj klasę A$Foo. Zastanawiam się, czy istnieje sztuczka, którą można wykorzystać, czy też nie. Mam wrażenie, że możliwe jest wygenerowanie źródła, które będzie skompilowane w tym samym kodzie bajtowym, co klasa wewnętrzna. W czasie kompilacji/środowiska wykonawczego JVM pobierze ją dla klasy wewnętrznej i umożliwi dostęp do prywatnych pól klasy zewnętrznej.Czy można wygenerować wewnętrzną klasę klasy do kompilacji za pomocą procesora adnotacji?

Ideą tego pytania, które nie jest pytaniem noobiego, choć może wyglądać bardziej lub mniej technicznie, jest możliwość użycia prywatnego modyfikatora widoczności dla pól opatrzonych adnotacją, takich jak Sztylet, MasłoKnife itp. Prywatny modyfikator dopuszczający w celu łatwiejszego wykrywania nieużywanych pól, podczas gdy ochrona prywatna pakietów ukrywa je.

Czy istnieje jakieś obejście, w jaki sposób, aby uzyskać jak najlepsze z obu słów?

+1

Nie. Nie można modyfikować istniejących plików źródłowych, wystarczy utworzyć nowe. Ale zawsze nazywam generowane klasy zgodnie z tym schematem, na przykład 'SomeInterface $ Impl', aby wskazać, że ta wygenerowana klasa należy do' SomeInterface'. –

+1

Ale wiem dokładnie, co masz na myśli, dużo grałem z przetwarzaniem adnotacji i używam go dużo w moich bibliotekach i chciałbym, żeby to było możliwe ... Zazwyczaj generuję prywatne końcowe klasy implementacji, a następnie generuję publiczna klasa fabryczna, która tworzy wystąpienia tych interfejsów z prywatnymi klasami implementacji. Można to nazwać obejściem. –

Odpowiedz

-2

Prywatna widoczność jest tylko wskazówką dla kompilatora. Nie ma problemu, aby uzyskać dostęp do tych pól w środowisku wykonawczym (tak jak robię to w moim małym wtryskiwaczu zależności: https://github.com/ko5tik/andject)

A niestatyczne klasy wewnętrzne na Androidzie są generalnie złym pomysłem, ponieważ dawniej były kary za wydajność.

W czasie kompilacji można użyć narzędzia do generowania źródeł, takiego jak xdoclet (chociaż stało się to technicznie przestarzałe lata temu, ale wciąż jest używane sporadycznie) i wygenerować wszystkie potrzebne źródła z góry przed ich skompilowaniem.

+2

W bibliotece, do której prowadzi łącze, używasz odbicia do wykonania wstrzyknięcia. W większości przypadków jest to dokładnie to, czego chcesz uniknąć podczas korzystania z przetwarzania adnotacji i generowania kodu. Generowany kod musi być prawidłowym kodem, a prawidłowy kod nie może uzyskać dostępu do prywatnych pól. –

+1

Prywatna widoczność nie jest "* tylko wskazówką dla kompilatora *". W domyślnym przypadku możesz uzyskać dostęp do prywatnych pól z refleksją, ale można to wyłączyć, jeśli twój kod działa w kontekście innego menedżera bezpieczeństwa. W takim przypadku 'Field.setAccessible' zgłasza' SecurityException'. – Lii

2

Biorąc pod uwagę Twój przypadek użycia, nie.

Wewnętrzna klasa to normalna klasa Java, żyjąca w innym pliku .class. Podczas kompilacji ukryty parametr konstruktora zostanie dodany do wewnętrznego konstruktora klasy. Prywatne pola w zewnętrznej klasie są udostępniane przez dodanie ukrytych metod dostępu w zewnętrznej klasie. Wszystko to dzieje się podczas kompilacji.

JVM nie ma z tym nic wspólnego. Jeśli wygenerujesz klasę, która "wygląda jak wewnętrzna klasa innej klasy", nie spowoduje to, że pola klasy zewnętrznej będą dostępne.

+0

Oto ogólna idea ograniczenia. W rzeczywistości dodanie kilku zrzutów javap -c klas wewnętrznych i zewnętrznych pomogłoby w uznaniu tej odpowiedzi za kanoniczną. – Snicolas

+0

Co więcej, dotyczy to tylko kompilatora javac, ecj AFAIK ma inny mechanizm wyrażania powiązania między klasami zewnętrznymi i wewnętrznymi. – Snicolas

Powiązane problemy