Аннотацияларни яратиш — жуда осон жараён, лекин баъзи қоидалар билан чегараланган. Энди улар амалда қаерда фойдали эканлигини тушунишимиз керак.
Келинг, ўз аннотациямизни қандай яратганимизни эслайлик.
Класслар ва методларни аннотация қилиш учун аннотация ёзамиз ва муаллиф ва версия ҳақидаги маълумотларни сақлаймиз:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
String author() default "Author";
String version() default "0.0";
}
Аннотация қўшган классларимиз:
@Info
public class MyClass1 {
@Info
public void myClassMethod() {}
}
@Info(version = "2.0")
public class MyClass2 {
@Info(author = "Anonymous")
public void myClassMethod() {}
}
@Info(author = "Anonymous", version = "2.0")
public class MyClass3 {
@Info(author = "Anonymous", version = "4.0")
public void myClassMethod() {}
}
Дастур ишлаётганда бу маълумотларни қандай фойдалансак бўлади?
Аннотациялардан метамаълумотларни рефлексия ёрдамида чиқариб олиш мумкин. Рефлексия нима эканини эслайлик. Бу дастур ишлаётганда ундаги маълумотларни тадқиқ қилиш механизми. Рефлексия қаторлар, методлар, класслар конструкторлари ҳақида маълумот олишга имкон беради.
Рефлексия ёрдамида биз классдаги аннотацияларни ўқиб чиқамыз ва керакли маълумотларни чиқарамиз.
mainдаги классларимиздан маълумотларни билиб оламиз:
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
readMyClass(MyClass1.class);
readMyClass(MyClass2.class);
readMyClass(MyClass3.class);
}
static void readMyClass(Class<?> myClassObj) throws NoSuchMethodException {
System.out.println("\nКласс " + myClassObj.getName());
readAnnotation(myClassObj);
Method method = myClassObj.getMethod("myClassMethod");
readAnnotation(method);
}
static void readAnnotation(AnnotatedElement element) {
try {
System.out.println("Поиск аннотаций в " + element.getClass().getName());
Annotation[] annotations = element.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof Info) {
final Info fileInfo = (Info) annotation;
System.out.println("Автор: " + fileInfo.author());
System.out.println("Версия: " + fileInfo.version());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
readMyClass методига класснинг экземплярини бериб, уни ишлатамиз.
Кейин readAnnotation методига ҳам класс, ҳам методни беришимиз мумкин. Шундай қилиб, биз класска ва методга объектни ўтамиз. AnnotatedElement контрактини ишлайдиган объект қабул қилинади. Бу аннотациялар рўйхатини ундан чиқариб олишга ва уларнинг ҳар бири ҳақидаги маълумотни ўқишга имкон беради.
Аннотацияни бизнинг аннотация туримизга тегишлилигини текширмасдан, биз маълумотларни ололмаймиз (if (annotation instanceof Info)).
Натижада аннотациялардан тўлиқ маълумот оламиз:
Поиск аннотаций в java.lang.Class
Автор: Author
Версия: 0.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Author
Версия: 0.0
Класс annotation.MyClass2
Поиск аннотаций в java.lang.Class
Автор: Author
Версия: 2.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Anonymous
Версия: 0.0
Класс annotation.MyClass3
Поиск аннотаций в java.lang.Class
Автор: Anonymous
Версия: 2.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Anonymous
Версия: 4.0
Шундай қилиб, рефлексия ёрдамида метамаълумотларни чиқариб олдик.
Энди кодни яхшилаш учун аннотациялардан фойдаланиш усулларини кўриб чиқамиз, жумладан, ўқишни яхшилаш, ишлаш тезлигини ошириш ва умумий сифатни яхшилаш. Бунда bizga Lombok ёрдам беради.
Lombok — бу компиляторга қўшиладиган плагин бўлиб, аннотация калит сўзлари ёрдамида кўп миқдордаги кодни яширади, тилни кенгайтириб, ишлаб чиқишни соддалаштиради ва баъзи функционалликни қўшади.
Lombok аннотацияларининг мисолини кўриб чиқамиз:
| @ToString | toString() методи учун амалга оширишни яратади, у объектнинг тозаланган талқинидан иборат: класс номи, барча майдонлар ва уларнинг қийматлари. | |
| @EqualsAndHashCode | equals ва hashCode амалга оширишларни яратади, улар ўзгарувчан ва стационар бўлмаган майдонлардан фойдаланиб, аммо мослаштирилади. | Батафсил маълумотни лойиҳа сайтда ўқиш мумкин. У ерда @EqualsAndHashCode билан ва ундан ташқари стандарт амалга ошириш билан мисол келтирилган. |
| @Getter / @Setter | Шахсий майдонлар учун getter ва setter яратади. | |
| @NonNull | Объект экземпляри яратилгандан кейин майдонларни null эмаслигини тасдиқлаш учун ишлатилади. Акс ҳолда, NullPointerException истисносидан чиқиб кетилади. | |
Lombok устида кўпроқ фойдали аннотациялар мавжуд, лекин улар камдан кам ишлатилади. Биз унинг аннотацияларининг бошланғич қисмини кўриб чикдик. Лойиҳа ҳақида кўпроқ маълумотни расмий сайтдан ўқиш мумкин.
GO TO FULL VERSION