前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java-注解入门指南

Java-注解入门指南

作者头像
PhoenixZheng
发布2018-08-07 16:11:30
3320
发布2018-08-07 16:11:30
举报

如果你是个Java开发者,一定用过,至少听说过注解。 注解是Java的一种手段,它的官方定义是

In the Java computer programming language, an annotation is a form of syntactic "metadata“ that can be added to Java source code.Classes, methods, variables, parameters and packages may be annotated.

看不懂吧,翻译成中文就是

注解是一种在Java源码上的附带的 metadata,类/方法/变量/参数和包都可以用到注解。

metadata有些翻译称作元数据,字面意思对于初学者来说实在不好理解,通俗的说就是一种"冗余数据",在功能之外的描述性数据。 有了这些基本概念后来看看一个注解怎么定义,怎么使用,还有原理是怎么实现的。 实现原理这块比较复杂,要涉及到class文件的数据结构,初学者可以选择性阅读这块内容,当然对进阶高级开发来说有必要了解一下。 原理这块我们下篇单独讲。

注解的定义

注解--Annotation, 首先有几个方面的概念需要明确

  • 作用对象:@Target
  • 作用域:@Retention

除了这两个之外还有类似于@Inhertied,@Documented 这种语法,这些高级语法我们不准备介绍,在明白了注解的基本脉络后可以自行学习。 一个注解至少需要有@Retention定义才能正常使用和工作。 回想在平时开发中见到的像 @Override,@TargetApi这些系统注解,是由系统开发者预先定义好了,我们再使用。 从这个角度出发可以把注解分成两类, 一种是已经定义好的像 @Override这种,归属于系统注解, 另外一种是 @Target 这种,归属于 元注解, 如果还没晕的话请往下看,晕了的缓一缓,先记住@Target和@Retention这两个注解。

圣人有云,read the fucking source code,下面贴个自定义注解的源码

代码语言:javascript
复制
import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Sexual {
    String value() default "Default";
}

一行行解释, 这段代码定义了一个自定义注解 Sexual,定义它的主要方法是用 @interface修饰。 定义完之后使用这个注解的方法跟@Override这种系统注解一样,还是拿一个万年例子类Student来说,

代码语言:javascript
复制
public class Student {
  String name;
  int age;

  public Student(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @Sexual(value="male") // <- 使用注解Sexual
  public static Student createStudent(String name, int age) {
    return new Student(name, age);
  }

  public void displayInfo() {
    System.out.println("name: " + this.name + " age: " + this.age);
  }
}

注释的这一行就使用了@Sexual注解了。

作用对象

现在回到注解的代码里来解释,@Target在参数中的是修饰对象,有以下这些

代码语言:javascript
复制
ElementType.Constructor 构造方法中
ElementType.Field  成员变量和枚举常量
ElementType.Local_Variable   局部变量
ElementType.Method   方法
ElementType.package   包
ElementType.parameter  方法参数
ElementType.type   接口,类,枚举,注解

比如@Sexual中用的是 METHOD,那么这个注解就可以用来修饰方法。

作用域

@Sexual中的Retention是 RUNTIME,除此之外还有 SOURCE, CLASS, 这三个分别表示的意思是

  • Source:注解只在Java源码中可见
  • Class:注解在源码和Class文件字节码中可见
  • Runtime:注解直到在运行时也可见

拿Sexual的代码来做例子,这里用的是 RUNTIME,意为着在运行时我们还可以拿到这个注解和它所附加的数据。

具体的用法,我们在下面这个代码里给出,这段代码在运行时构造一个Student对象,然后从Student中被注解的方法里拿到注解所设定的value值。

使用注解
代码语言:javascript
复制
import java.lang.Class;
import java.lang.reflect.Method;

public class AnnotationDemo {
    public static void main(String[] args) {
      Student michael = Student.createStudent("Michael", 10);
      michael.displayInfo();

      Class clazz = michael.getClass();
      Method[] methods = clazz.getMethods();
      for(Method method : methods) {
        if(method.isAnnotationPresent(Sexual.class)) {
          Sexual sexual = method.getAnnotation(Sexual.class);
          System.out.println("Student: " + michael.name + " sexual: " + sexual.value());
        }
      }
    }
}

简单解释这段代码, 先 createStudent传入了参数构造了对象 michael,这里很简单。 然后我们从 michael对象中拿到它的类,并用 getAnnotation方法拿到类中所注解的内容。 如果你是第一次接触注解,那么需要留意一下,注解是针对类/文件的,它的目标并不是对象,上面的例子我们只是从对象中去拿它的类而已,如果直接通过Student拿类,也是可以的。

解释下这个demo做的事情。 Method类提供了一些提取注解的方法,

  • isAnnotationPresent,检查是否带某个注解
  • getAnnotation,获取对应注解

所以逻辑上是通过反射拿到各个方法之后,检查方法是否有注解,然后拿到这个注解的 value。

定义注解的时候参数是可选的,各种基本类型都可以,像上面我们定义的Sexual就带了个String类型叫value的参数。 在Student类中传入了"male",并且它的类型是RUNTIME,所以在运行时就可以拿到。对应的如果是SOURCE类型的话那在运行时就拿不到了。

注解的应用

上面的例子只是说明了注解的工作流程,对于注解来说应用不止于此。 很多牛逼的框架都是通过注解来工作的,比方在Android上的ButterKnife,你肯定体会过它的方便,只用注解就代替了我们传统的 findViewById等繁琐的重复劳动。 它的原理也就是在编译时通过注解拿到这些方法/对象后,替我们插入 findViewById这些方法。 所以说在通往Java高级开发的路上,总会在某个点发现注解的强大作用,如果能掌握好注解的原理,在理解高级框架上会节省很多时间呢。希望这篇文章能帮你理清注解的脉络,以后遇到了问题可以自学解决。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 注解的定义
    • 作用对象
      • 作用域
      • 使用注解
      • 注解的应用
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档