简体   繁体   English

使用自定义注释

[英]use of custom annotations

I found several related (not duplicate) question to this, but they didn't satisfy me. 我发现了几个相关(不重复)的问题,但他们并不满足我。

I am unable to understand where and why to use custom annotations ? 我无法理解使用custom annotations位置和原因?

I read an example of custom annotation in a book, but it was not explained thoroughly. 我在一本书中读到了一个自定义注释的例子,但没有详细解释。

@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();
    }
}

The output is as expected Inside myMeth() . 输出如预期的那样Inside myMeth()

I am having few questions regarding this example. 关于这个例子我几乎没有问题。

1- How can I use String str() and int val() in this program? 1-如何在此程序中使用String str()int val() OR 要么

What is the use of any abstract method of an custom annotation ? custom annotation的任何抽象方法有什么用?

2- Why custom annotations . 2-为什么要custom annotations I mean that what effect they are having on any code. 我的意思是他们对任何代码都有什么影响。

3- How can I create an annotation which is having effects like @override is having?(I mean any kind of effect which can be noticed) 3-如何创建一个具有@override效果的注释?(我的意思是任何可以注意到的效果)

If this example is useless for you, then please give me a suitable small example in which a custom annotation is used. 如果这个例子对你没用,那么请给我一个合适的小例子,其中使用了custom annotation

Three main reasons to use custom annotations are: 使用自定义注释的三个主要原因是:

  • To reduce the effort of writing code (a compile-time annotation processor generates code for you). 减少编写代码的工作量(编译时注释处理器为您生成代码)。 Here is a tutorial: part 1 , part 2 . 这是一个教程: 第1 部分第2部分
  • To provide additional correctness guarantees (a compile-time annotation processor warns you about errors). 提供额外的正确性保证(编译时注释处理器会警告您错误)。 One nice tool for this is the Checker Framework , which prevents null pointer dereferences, concurrency errors, and more. 一个很好的工具是Checker Framework ,它可以防止空指针解引用,并发错误等。
  • To customize behavior (at run time, your code checks for the annotation using reflection and behaves differently depending on whether the annotation is present). 要自定义行为(在运行时,您的代码使用反射检查注释,并根据注释是否存在而表现不同)。 Frameworks such as Hibernate use annotations this way; Hibernate这样的框架以这种方式使用注释; also see an Oracle article . 另见Oracle文章

In each case, use of annotations reduces the likelihood of errors in your code, compared to other non-annotation approaches. 在每种情况下,与其他非注释方法相比,使用注释可以降低代码中出错的可能性。

Here is a minimal example. 这是一个最小的例子。 The following code demonstrates use of custom annotation. 以下代码演示了自定义注释的使用。

It is about Employees and Benefits. 这是关于员工和福利。 If we have a requirement such that BasicBenefits has to be applied to all types of employess then we can come up with custom annotation such as BasicBenefits, and annotate all types of Employee implementations (eg CorporateEmployee, ContractEmployee, ManagerEmployee etc. etc.) with the BasicBenefits. 如果我们要求BasicBenefits必须应用于所有类型的雇员,那么我们可以提出自定义注释,例如BasicBenefits,并注释所有类型的Employee实现(例如,CorporateEmployee,ContractEmployee,ManagerEmployee等等)。 BasicBenefits。

Custom Annotation Class(interface) 自定义注释类(界面)

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";
}

Class using the custom annotation(no need of any imports): 使用自定义注释的类(不需要任何导入):

@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);
    }
}

Driver class to test out the above. 驱动程序类来测试上面的内容。

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());
    }
}

Your code look almost there, just two things need to be included in the main method. 你的代码几乎就在那里,main方法中只需要包含两件事。

1.) Need reference to MyClass 2.) Need to get the annotation using reflection from MyClass. 1.)需要参考MyClass 2.)需要使用MyClass的反射来获取注释。

Here is a bit modified code from what you have: 以下是您所拥有的一些修改过的代码:

@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());     
    }
}

The abstract methods of the annotation define the values you can pass to it (in your case str = "Annotation example", val = 100 ). 注释的抽象方法定义了可以传递给它的值(在你的情况下str = "Annotation example", val = 100 )。 You can access them using reflection ( Method.<T>getAnnotation(Class<T>) ). 您可以使用反射( Method.<T>getAnnotation(Class<T>) )访问它们。 Custom annotations don't have direct impact. 自定义注释没有直接影响。 They are only useful if you evaluate them. 它们仅在您评估它们时才有用。

Note that you have to annotate your custom annotation with @Retention(value=RUNTIME) to be able to read it via reflection. 请注意,您必须使用@Retention(value=RUNTIME)注释自定义注释才能通过反射读取它。

To be of any use, annotations must be parsed first. 作为任何用途,必须首先解析注释。 The built-in annotations (such as @Override or @FunctionalInterface , to name the most obvious ones) are parsed by the compiler itself. 内置注释(例如@Override@FunctionalInterface ,用于命名最明显的注释)由编译器本身解析。 As for custom annotations, these guys are commonly parsed by third-party frameworks, although we can also use the reflection mechanism to demonstrate this technique in standalone code. 至于自定义注释,这些人通常由第三方框架解析,尽管我们也可以使用反射机制在独立代码中演示这种技术。

By way of an example, the code below changes its behaviour at run time depending on the value of the field declared in the custom annotation named @SwitchingAnnotation : 举例来说,下面的代码在运行时更改其行为,具体取决于名为@SwitchingAnnotation的自定义注释中声明的字段的值:

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface SwitchingAnnotation{
    boolean flag();
}

public class Worker{
    void doThis(){ System.out.println("Doing this"); }
    void doThat(){ System.out.println("Doing that"); }
    @SwitchingAnnotation(
        flag = false
    )
    public void work(boolean flag) {
        if (flag) doThis();
        else doThat();
    }
}

class Test{
    public static void main(String[] args) {
        try{
            SwitchingAnnotation sw = Worker.class.getMethod("work", boolean.class)
                                                 .getAnnotation(SwitchingAnnotation.class);

            new Worker().work(sw.flag());    // prints Doing that
        }
        catch(NoSuchMethodException nsme){
            System.out.println(nsme);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM