Использование пользовательских аннотаций

Я нашел несколько связанных (не дублированных) вопросов, но они меня не удовлетворили.

Я не могу понять, где и почему использовать custom annotations?

Я прочитал пример пользовательской аннотации в книге, но он не был подробно объяснен.

@interface MyAnno
{
    String str();
    int val();
}

class MyClass
{
    @MyAnno(str = "Annotation example", val = 100)
    public static void myMeth()
    {
        System.out.println("Inside myMeth()");
    }
}

class CustomAnno
{
    public static void main(String args[])
    {
        MyClass.myMeth();
    }
}

Вывод будет таким, как ожидалось Inside myMeth().

У меня мало вопросов относительно этого примера.

1- Как я могу использовать String str() и int val() в этой программе? ИЛИ

Какое использование абстрактного метода custom annotation?

2- Почему custom annotations. Я имею в виду, какое влияние они оказывают на любой код.

3 Как создать аннотацию, которая имеет такие эффекты, как @override, имеет? (я имею в виду любой вид эффекта, который можно заметить)

Если этот пример для вас бесполезен, пожалуйста, дайте мне подходящий небольшой пример, в котором используется custom annotation.

Ответ 1

Вот минимальный пример. Следующий код демонстрирует использование пользовательской аннотации.

Это о сотрудниках и преимуществах. Если у нас есть требование, чтобы BasicBenefits применялось ко всем типам работодателей, тогда мы можем придумать пользовательскую аннотацию, такую ​​как BasicBenefits, и аннотировать все типы реализаций Employee (например, CorporateEmployee, ContractEmployee, ManagerEmployee и т.д.) С помощью BasicBenefits.

Пользовательский класс аннотации (интерфейс)

import java.lang.annotation.*;
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)

@interface BasicBenefits {
    String bId() default "B-101";
    String bName() default "General Class A Employee";
}

Класс с использованием пользовательской аннотации (без необходимости импорта):

@BasicBenefits(bId="B-400", bName="General Plus Class A Employee")
public class Employee {
    String eId;
    String eName;
    public Employee(String eId, String eName){
        this.eId = eId;
        this.eName = eName;
    }

    public void getEmployeeDetails(){
        System.out.println("Employee ID: "+eId);
        System.out.println("Employee Name: "+eName);
    }
}

Класс драйвера, чтобы проверить выше.

import java.lang.annotation.Annotation;
public class TestCustomAnnotationBasicBenefits {
    public static void main(String[] args) throws Exception{
        Employee emp = new Employee("E-100", "user3320018");
        emp.getEmployeeDetails();
        Class reflectedClass = emp.getClass();
        Annotation hopeBenefitAnn = reflectedClass.getAnnotation(BasicBenefits.class);
        BasicBenefits bBenefits = (BasicBenefits)hopeBenefitAnn;
        System.out.println("Benefit ID: "+bBenefits.bId());
        System.out.println("Benefit Name: "+bBenefits.bName());
    }
}

Ваш код выглядит почти там, только две вещи должны быть включены в основной метод.

1.) Нужна ссылка на MyClass 2.) Нужно получить аннотацию, используя отражение от MyClass.

Вот немного измененный код из того, что у вас есть:

@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno
{
    String str();
    int val();
}

//using above custom annotation on class level
//can also use method level
//just need to change t @Target(ElementType.METHOD)
@MyAnno(str = "Annotation example", val = 100)
class MyClass
{

    public static void myMeth()
    {
        System.out.println("Inside myMeth()");
    }
}

import java.lang.annotation.Annotation;
class CustomAnno
{
    public static void main(String args[])
    {
        //1. getting reference to the class where the custom annotation is applied.
        //2. then getting the annotation to get the values 
        MyClass myClass = new MyClass();
        Class cls = myClass.getClass();
        Annotation getMyAnno = cls.getAnnotation(MyAnno.class);
        MyAnno myAnno = (MyAnno)getMyAnno;
        MyClass.myMeth(); //left this as is.
        System.out.println("myAnno.str(): "+ myAnno.str());
        System.out.println("myAnno.str(): "+ myAnno.val());     
    }
}

Ответ 2

Три основные причины использования пользовательских аннотаций:

  • Чтобы уменьшить усилие написания кода (процессор компиляции времени аннотации генерирует для вас код). Вот учебник: часть 1, часть 2.
  • Чтобы предоставить дополнительные гарантии корректности (процессор комментариев компиляции предупреждает вас об ошибках). Одним из хороших инструментов для этого является Checker Framework, который предотвращает поиск нулевых указателей, ошибки concurrency и т.д.
  • Чтобы настроить поведение (во время выполнения ваш код проверяет аннотацию с использованием отражения и ведет себя по-разному в зависимости от присутствия аннотации). Такие рамки, как Hibernate, используют аннотации таким образом; также см. статья Oracle.

В каждом случае использование аннотаций уменьшает вероятность ошибок в вашем коде по сравнению с другими подходами, не связанными с аннотацией.

Ответ 3

Абстрактные методы аннотации определяют значения, которые вы можете передать ему (в вашем случае str = "Annotation example", val = 100). Вы можете получить к ним доступ с помощью отражения (Method.<T>getAnnotation(Class<T>)). Пользовательские аннотации не имеют прямого воздействия. Они полезны только при их оценке.

Обратите внимание, что вы должны аннотировать свою пользовательскую аннотацию @Retention(value=RUNTIME), чтобы читать ее с помощью отражения.