अपनी एनोटेशन प्रोसेसर चलाने पर, आपके पास संकलित कक्षाओं तक पहुंच नहीं है। एनोटेशन प्रसंस्करण का बिंदु यह है कि यह पूर्व संकलन होता है।
इसके बजाय, आपको एक एनोटेशन प्रोसेसर बनाना होगा जो विशेष रूप से आपके एनोटेशन प्रकार को संभालता है, फिर फ़ील्ड तक पहुंचने के लिए दर्पण API का उपयोग करें। उदाहरण के लिए:
@SupportedAnnotationTypes("com.example.MyAnnotation")
public class CompileTimeAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// Only one annotation, so just use annotations.iterator().next();
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(
annotations.iterator().next());
Set<VariableElement> fields = ElementFilter.fieldsIn(elements);
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
// Validate fullTypeClassName
}
return true;
}
}
सत्यापन के लिए, आप अभी तक (उन है कि के बारे में टिप्पणी के साथ संकलित किया जा रहे हैं सहित) संकलित की MyType.class
की तरह कुछ का उपयोग कर जो किसी भी कक्षाओं का उपयोग नहीं कर सकते हैं। इनके लिए, आपको तारों का उपयोग केवल करना होगा। ऐसा इसलिए है क्योंकि एनोटेशन प्रोसेसिंग प्री-कंपाइलिंग चरण के दौरान होती है जिसे "सोर्स पीढ़ी" कहा जाता है, जो कि संकलन का उपयोग करके कंपाइलर चलाने से पहले आपको स्रोत कोड उत्पन्न करने की अनुमति देता है।
एक उदाहरण सत्यापन सत्यापित करें कि फ़ील्ड प्रकार java.lang.String
(जो पहले से ही संकलित किया गया है) है:
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
if (!String.class.getName().equals(fullTypeClassName)) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field type must be java.lang.String", field);
}
}
संसाधन
संपादित करें:
मैं उस प्रकार पर भी टिप्पणियां प्राप्त करने के लिए फ़ील्ड प्रकार प्राप्त करना चाहते हैं। लेकिन ऐसा प्रतीत नहीं होता है कि यह संभव होगा?
वास्तव में यह संभव है!यह TypeMirror
के बारे में अधिक तरीकों का उपयोग कर किया जा सकता है:
if (fieldType.getKind() != TypeKind.DECLARED) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field cannot be a generic type.", field);
}
DeclaredType declaredFieldType = (DeclaredType) fieldType;
TypeElement fieldTypeElement = (TypeElement) declaredFieldType.asElement();
यहां से, आप दो विकल्प हैं:
- एनोटेशन आप खोजने की कोशिश कर रहे हैं पहले से ही संकलित किया गया है (अर्थात यह एक और पुस्तकालय से है) तो आप एनोटेशन प्राप्त करने के लिए सीधे कक्षा का संदर्भ दे सकते हैं।
- एनोटेशन आप खोजने की कोशिश कर रहे हैं संकलित नहीं किया है तो आप इसे
AnnotationMirror
उदाहरणों के माध्यम से संदर्भित कर सकते हैं (यानी यह है कि अपार्ट चल javac
को वर्तमान कॉल में संकलित किया जा रहा है)।
पहले से ही,
DifferentAnnotation diffAnn = fieldTypeElement.getAnnotation(
DifferentAnnotation.class);
// Process diffAnn
बहुत सीधी-सपाट संकलित इस आप एनोटेशन खुद के लिए सीधी पहुँच देता है।
संकलित नहीं
ध्यान दें कि यह समाधान एनोटेशन संकलित किया गया है या नहीं, की परवाह किए बिना काम करेंगे, यह सिर्फ ऊपर कोड के रूप में के रूप में साफ नहीं है।
private static <T> T findAnnotationValue(Element element, String annotationClass,
String valueName, Class<T> expectedType) {
T ret = null;
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
DeclaredType annotationType = annotationMirror.getAnnotationType();
TypeElement annotationElement = (TypeElement) annotationType
.asElement();
if (annotationElement.getQualifiedName().contentEquals(
annotationClass)) {
ret = extractValue(annotationMirror, valueName, expectedType);
break;
}
}
return ret;
}
private static <T> T extractValue(AnnotationMirror annotationMirror,
String valueName, Class<T> expectedType) {
Map<ExecutableElement, AnnotationValue> elementValues = new HashMap<ExecutableElement, AnnotationValue>(
annotationMirror.getElementValues());
for (Entry<ExecutableElement, AnnotationValue> entry : elementValues
.entrySet()) {
if (entry.getKey().getSimpleName().contentEquals(valueName)) {
Object value = entry.getValue().getValue();
return expectedType.cast(value);
}
}
return null;
}
मान लीजिए कि आप DifferentAnnotation
एनोटेशन की तलाश कर रहे हैं और अपने स्रोत कोड की तरह दिखता है:
यहां कुछ तरीकों मैं एक बार लिखा था अपने वर्ग नाम से एक टिप्पणी के दर्पण से एक निश्चित मान प्राप्त करने के हैं इस:
@DifferentAnnotation(name = "My Class")
public class MyClass {
@MyAnnotation
private String field;
// ...
}
इस कोड My Class
प्रिंट होगा:
String diffAnnotationName = findAnnotationValue(fieldTypeElement,
"com.example.DifferentAnnotation", "name", String.class);
System.out.println(diffAnnotationName);
आप 'Field.getType()' का उपयोग क्यों नहीं करते? – Desert
क्योंकि मैं ओ मेरी टिप्पणियों में एक फील्ड उदाहरण के लिए पहुँच नहीं precessor जहाँ तक मुझे पता –