Jest kilka problemów tutaj. Możesz być zainteresowany znając typ Java odbiornika wywołania metody lub po prostu wiedząc, że klasa w tej metodzie jest wywoływana. Informacje Java są bardziej informacyjne, ponieważ dają także ogólne typy, np. List<String>
, podczas gdy elementy zapewniłyby Tobie tylko klasę, np. List<E>
.
Pierwsze Element
Aby uzyskać element klasy metoda wywoływana jest, można zrobić następujące:
MethodInvocationTree node = ...;
Element method =
TreeInfo.symbol((JCTree)node.getMethodSelect());
TypeElement invokedClass = (TypeElement)method.getEnclosingElement();
przypadkach róg:
1. invokedClass może być nadklasą typu odbiornika. Tak działa fragment na new ArrayList<String>.equals(null)
wróci AbstractList
zamiast ArrayList
, ponieważ równych() jest realizowany w AbstractList
nie ArrayList
.
2. Podczas obsługi wywołań tablicy, np. new int[].clone()
, można uzyskać uzyskać TypeElement
klasy Array
.
Uzyskiwanie rzeczywisty typ
Aby uzyskać typ, nie istnieje bezpośredni sposób określania go co typ odbiornik. Istnieje pewna złożoność wywołań metod obsługi w obrębie klas wewnętrznych, w których odbiornik nie jest wyraźnie określony (np. W przeciwieństwie do OuterClass.this.toString()
). Oto próbka realizacja:
MethodInvocationTree node = ...;
TypeMirror receiver;
if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) {
ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression();
receiverType = ((JCTree)receiver).type;
} else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) {
// need to resolve implicit this, which is described in
// JLS3 15.12.1 and 15.9.2
// A bit too much work that I don't want to work on now
// Look at source code of
// Attr.visitApply(JCMethodInvocation)
// resolveImplicitThis(DiagnosticPosition, Env, Type)
} else
throw new AssertionError("Unexpected type: " + methodSel.getKind());
Uwaga:
Typ receiver
musi być TypeMirror
nie DeclaredType
niestety. Podczas wywoływania new int[5].clone()
, będzie bardziej informacyjny niż poprzedni metoda .
Uzyskanie go uruchomić
oba poprzednich metod wymagają kompilator rozpoznać typ informacji dla klas. W zwykłych okolicznościach kompilator rozwiązuje tylko typy deklaracji metod, ale nie ciał. W związku z tym opisane wcześniej metody zwrócą numer null
.
Aby kompilator rozwiązać wpisz informacje, można wykonać jedną z następujących sposobów:
1. Zastosowanie AbstractTypeProcessor
klasy, który właśnie został dodany do repozytorium kompilatora dla JDK 7. Sprawdź pracy na JSR 308 i ich kompilator. Podczas gdy praca dotyczy głównie typów z przypisami, może być przydatna. Kompilator pozwala na użycie dostarczonego klasę w zacofanym sposób zgodny z Java 5.
Takie podejście pozwala na pisanie procesory, które się powoływać tylko jak aktualnych procesorów.
2. Zamiast tego należy użyć JavacTask
i zadzwonić pod numer JavacTask.analyze()
. Spójrz na główną metodą pod numerem this javac test, aby zobaczyć, w jaki sposób można wywołać swojego gościa na zajęciach.
Takie podejście sprawia, że procesor wygląda bardziej jak narzędzie analityczne niż wtyczka do kompilatora, ponieważ trzeba go wywoływać bezpośrednio, a nie jako zwykły proces.
Dziękuję za odpowiedź. Jednak linia: Metoda elementu = TreeInfo.symbol ((JCTree) node.getMethodSelect()); zwraca dla mnie wartość null. \t TypeMirror m = trees.getTypeMirror (ścieżka); zwraca także wartość null, podobnie jak \t TypeElement e = (TypeElement) trees.getElement (ścieżka); Czy popełniam błąd debiutanta i zapominając o zainicjowaniu czegoś lub wywołaniu/przesłonięciu niewłaściwej metody lub podklasowaniu czegoś złego? Jeszcze raz dziękuję za pomoc ... – runT1ME
Właśnie zaktualizowałem wpis, aby wyjaśnić, dlaczego metody zwracają wartość null i jak adresować ten numer: – notnoop
, AbstractTypeProcessor nie jest już dostępny w kompilacjach JDK 7, ponieważ obsługa JSR 308 została usunięta. –