Có một vài vấn đề ở đây. Bạn có thể quan tâm đến việc biết loại Java của trình thu thập lời gọi phương thức hoặc chỉ biết rằng lớp trên phương thức được gọi. Thông tin Java có nhiều thông tin hơn vì nó cung cấp cho bạn các loại chung chung, ví dụ: List<String>
trong khi Elements chỉ cung cấp cho bạn lớp học, ví dụ: List<E>
.
Bắt Element
Để có được phần tử của lớp phương pháp này được gọi trên, bạn có thể làm sau:
MethodInvocationTree node = ...;
Element method =
TreeInfo.symbol((JCTree)node.getMethodSelect());
TypeElement invokedClass = (TypeElement)method.getEnclosingElement();
trường hợp Corner:
1. invokedClass có thể là một siêu lớp của kiểu người nhận. Vì vậy, hãy chạy đoạn mã trên new ArrayList<String>.equals(null)
sẽ trả lại AbstractList
thay vì ArrayList
, vì equals() được triển khai trong AbstractList
không ArrayList
.
2. Khi xử lý yêu cầu mảng, ví dụ: new int[].clone()
, bạn sẽ nhận được TypeElement
của lớp Array
.
Bắt loại thực
Để có được loại, không có cách nào trực tiếp để xác định nó những gì các loại nhận là. Có một số phức tạp trong việc xử lý các lời gọi phương thức trong các lớp bên trong nơi người nhận không được cung cấp rõ ràng (ví dụ: không giống như OuterClass.this.toString()
). Đây là một thực hiện mẫu:
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());
Lưu ý:
Loại receiver
cần phải được TypeMirror
không DeclaredType
không may. Khi gọi new int[5].clone()
, receiver
sẽ là an ArrayType
trong số int[]
, thông tin đó nhiều thông tin hơn phương pháp trước đó.
Bắt nó chạy
Cả hai phương pháp trước đòi hỏi trình biên dịch để giải quyết các loại thông tin cho các lớp học. Trong các trường hợp thông thường, trình biên dịch chỉ giải quyết các loại khai báo phương thức chứ không giải quyết các đối tượng. Do đó, các phương pháp được mô tả trước đó sẽ trả lại null
thay thế.
Để có trình biên dịch giải quyết các loại thông tin, bạn có thể làm một trong các cách sau:
1. Sử dụng AbstractTypeProcessor
lớp mà chỉ đã được bổ sung vào kho trình biên dịch cho JDK 7. Kiểm tra hiện công việc trên JSR 308 và trình biên dịch của chúng. Trong khi tác phẩm chủ yếu dựa trên các loại chú thích, nó có thể hữu ích cho. Trình biên dịch cho phép bạn sử dụng lớp được cung cấp theo cách tương thích lạc hậu với Java 5.
Cách tiếp cận này cho phép bạn viết các bộ vi xử lý được gọi chỉ như bộ vi xử lý hiện tại của bạn.
2. Sử dụng JavacTask
thay vào đó và gọi JavacTask.analyze()
. Hãy xem phương pháp chính của this javac test để xem cách để gọi khách truy cập của bạn trên các lớp học.
Phương pháp này làm cho bộ xử lý của bạn trông giống như một công cụ phân tích hơn là trình cắm vào trình biên dịch, vì bạn cần gọi trực tiếp số thay vì phải là quy trình thông thường.
Cảm ơn bạn đã phản hồi. Tuy nhiên, dòng: Phương thức phần tử = TreeInfo.symbol ((JCTree) node.getMethodSelect()); trả về giá trị null cho tôi. \t TypeMirror m = trees.getTypeMirror (đường dẫn); cũng trả về null, cũng như \t TypeElement e = (TypeElement) trees.getElement (đường dẫn); Tôi có mắc lỗi tân binh và quên khởi tạo một cái gì đó, hoặc gọi/ghi đè sai phương pháp, hoặc phân lớp sai? Một lần nữa xin cảm ơn sự giúp đỡ của bạn ... – runT1ME
Tôi vừa cập nhật mục để giải thích lý do tại sao các phương thức trả về null và cách giải quyết – notnoop
FYI, AbstractTypeProcessor không còn khả dụng trong bản dựng JDK 7 nữa, vì hỗ trợ cho JSR 308 đã bị loại bỏ. –