美文网首页
Java之 注解

Java之 注解

作者: 五月笙 | 来源:发表于2021-09-02 16:59 被阅读0次

什么是注解

概念

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.

作用

Annotations have a number of uses, among them:
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
Runtime processing — Some annotations are available to be examined at runtime.

  • 标记,用于告诉编译器一些信息

  • 编译时动态处理,如动态生成代码

  • 运行时动态处理,如得到注解信息

参考:
Java Annotation
Java Reflection - Annotations

注解的使用

格式

一个注解由一个@符号后面跟字符串组成,例如:

@Entity

java注解里面一般包含一些元素,这些元素类似于属性或者参数,可以用来设置值,比如我们有一个包含两个元素的@Entity注解:

@Entity(name="mzw", job="码农")

该注解有两个元素,name和job,分别赋予了元素值。

位置

注解可以用于描述一个类、接口、方法、方法参数、字段、局部变量等。

  • 方法:
@Override
public void mySuperMethod() { ... }

@SuppressWarnings(value = "unchecked")
public void myMethod() { ... }
@Author(
      name = "zphuan",
      date = "3/24/2017"
   )
public class MyClass() { ... }
  • 方法参数
pulic void myMethod(@RequestParam String s){ ... }
  • 局部变量
@Autowired
private MyClass myClass;

细节

  • 如果注解没有参数,则不用加参数,如:@Override

  • 如果注解只有一个参数,那么参数名字可以省略,如:

@SuppressWarnings("unchecked")
public void myMethod() { ... }
  • 一个地方可以使用多个注解,如:
@Author(name = "Jane Doe")
@EBook
public class MyClass { ... }
  • 可以重复使用注解,不过只有在java SE 8 才支持。比如:
@Author(name = "Jane Doe")
@Author(name = "John Smith")
public class MyClass { ... }

表明有两个人对该类进行了代码编写。

内置注解

java本身提供了三个内置注解:

  • @Override
    注解是一个编译时注解,它主要用在一个子类的方法中,当被注解的子类的方法在父类中找不到与之匹配的方法时,编译器会报错。
  • @Deprecated
    可以用来描述一个类、方法或者字段,表示java不赞成使用这些被描述的对象,如果我们使用了这些类、方法或者字段,编译器会给我们警告。
  • @SuppressWarnings
    作用是使编译器忽略掉编译器警告。比如,如果我们的一个方法调用了一个@Deprecated方法,或者做了一个不安全的类型转换,此时编译器会生成一个警告。如果我们不想看到这些警告,我们就可以使用@SuppressWarnings注解忽略掉这些警告。

自定义注解

元注解

元注解就是用来描述注解的注解,在java里面有下面几个元注解:

  • @Documented
    作用是告诉JavaDoc工具,当前注解本身也要显示在Java Doc中。
  • @Retention
    用来定义注解的范围,有下面三个范围:
  1. RetentionPolicy.SOURCE
    注解只存在于源码中,不会存在于.class文件中,在编译时会被忽略掉。
  2. RetentionPolicy.CLASS
    注解只存在于.class文件中,在编译期有效,但是在运行期会被忽略掉,这也是默认范围。
  3. RetentionPolicy.RUNTIME
    在运行期有效,JVM在运行期通过反射获得注解信息。
  • @Target
    用于指定注解作用于java的哪些元素,未标注则表示可修饰所有。

ElementType.ANNOTATION_TYPE  Annotation type declaration
ElementType.CONSTRUCTOR  Constructor declaration
ElementType.FIELD  Field declaration (includes enum constants)
ElementType.LOCAL_VARIABLE  Local variable declaration
ElementType.METHOD  Method declaration
ElementType.PACKAGE  Package declaration.
ElementType.PARAMETER  Parameter declaration
ElementType.TYPE  Class, interface (including annotation type), or enum declaration

  • @Inherited
    注解表示当前注解会被注解类的子类继承。

参考:
Java Doc

注解解析

运行时注解

首先,先定义一个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {

    public String name();

    public String job();
}

上面通过元注解的定义,可以看出来自定义的注解是运行时注解,可以修饰所有的类型。

类注解
@MyAnnotation(name = "mzw", job = "给类添加了一个注解")
public class TestAnnotation { ... }

现在当程序运行起来的时候我想要获取到TestAnnotation中的@MyAnnotation的注解信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyAnnotation annotation = TestAnnotation.class.getAnnotation(MyAnnotation.class);
        Log.e("mzw", "name == " + annotation.name());
        Log.e("mzw", "value == " + annotation.value());
    }
}

运行后执行结果为:

24603-24603/demo.remer.myannotation E/mzw: name == mzw
24603-24603/demo.remer.myannotation E/mzw: value == 给类添加了一个注解
方法注解
public class TestAnnotation {

    @MyAnnotation(name = "mzw", value = "给方法添加了一个注解")
    public void test(){

    }
}

当程序运行时,可以获取到类中test方法注解的信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            Class clazz = Class.forName(TestAnnotation.class.getName());
            for (Method method : clazz.getMethods()) {
                MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
                if (annotation != null) {
                    Log.e("mzw", "name === " + method.getName() + "||" + annotation.name());
                    Log.e("mzw", "value == " + method.getName() + "||" + annotation.value());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

运行执行的结果为:

20791-20791/demo.remer.myannotation E/mzw: name === test||mzw
20791-20791/demo.remer.myannotation E/mzw: value == test||给方法添加了一个注解
参数注解
public class TestAnnotation {

    public static void test(@MyAnnotation(name = "参数", value = "参数上的注解") String parameter){ ... }
}

运行程序,可以获取到方法上的参数注解信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            Class clazz = Class.forName(TestAnnotation.class.getName());
            for (Method method : clazz.getMethods()) {
                Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                Class[] parameterTypes = method.getParameterTypes();

                int i = 0;
                for (Annotation[] annotations : parameterAnnotations) {
                    Class parameterType = parameterTypes[i++];
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof MyAnnotation) {
                            MyAnnotation myAnnotation = (MyAnnotation) annotation;
                            Log.e("mzw", "param === " + parameterType.getName());
                            Log.e("mzw", "name === " + myAnnotation.name());
                            Log.e("mzw", "value === " + myAnnotation.value());
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

运行执行的结果为:

17392-17392/demo.remer.myannotation E/mzw: param === java.lang.String
17392-17392/demo.remer.myannotation E/mzw: name === 参数
17392-17392/demo.remer.myannotation E/mzw: value === 参数上的注解

注意
isAnnotationPresent(AnnotationName.class) 可以判断Target是否被某个注解修饰

相关文章

  • Java——注解(Annotation)入门学习

    学习资料: Java编程思想 ——第20章 公共技术点之 Java 注解 Annotation 注解(Annota...

  • Spring注解原理探索(三)

    之 Java如何识别注解 关键词:Java 反射java.lang.reflect 包,实现反射功能的工具类。注解...

  • Spring注解原理探索(一)

    之 Java元注解释义 Question 注解在Java中如何起作用? Spring是如何识别注解? 如何自定义注...

  • 干货系列之java注解

    干货系列之java注解 前言 java反射和注解在java里面很重要,但是很多人对这方面的知识理解不是很好,我来说...

  • 菜鸟学服务端技术----Spirng基础

    注解 Java基础加强总结(一)——注解(Annotation) java中的注解是如何工作的? java 注解 ...

  • 自定义注解

    java annotation基础 java注解分为标准注解和元注解。 标准注解是java为我们提供的预定义的注解...

  • Java注解的使用

    Java注解的使用 参考 廖雪峰java教程 使用注解 什么是注解(Annotation)?注解是放在Java源码...

  • Java原生注解和Spring注解的说明

    注解 java 原生注解 Spring 中的注解 一 Java原生注解 Java注解是在JDK1.5以后引入的新特...

  • Java 注解

    JAVA注解 Java 自带注解(系统注解) @Override 表示重写注解 @Deprecated 表示过时的...

  • Spring注解原理探索(二)

    之 Java中如何自定义注解 1.先看注解定义示例 @Override 源码定义: 使用@interface 表示...

网友评论

      本文标题:Java之 注解

      本文链接:https://www.haomeiwen.com/subject/iepmnktx.html