java注解生命周期_Java注解学习笔记

前言

一直都在使用注解,但是一直都没有用的很明白,后来被逼的发现不搞明白真的就没有办法愉快的写代码了,所以,这篇《Java中的注解学习笔记》就呼之欲出了,在我的各种不情愿之下,在我浪费了好几个小时的情况下,总算对这个注解有了一个入门的学习,对付一般的注解问题是足够了。

注解说明

Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据。为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取注解内容。在编译器生成类文件时,注解可以被嵌入到字节码中。Java虚拟机可以保留注解内容,在运行时可以获取到注解内容。

内置注解

Java定义了一套注解,共有7个,3个在java.lang中,剩下4个在java.lang.annotation中。

作用在代码的注解是:

@Override – 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

@Deprecated – 标记过时方法。如果使用该方法,会报编译警告。

@SuppressWarnings – 指示编译器去忽略注解中声明的警告。

作用在其他注解的注解(或者说元注解)是:

@Retention – 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

@Documented – 标记这些注解是否包含在用户文档中。

@Target – 标记这个注解应该是哪种Java成员。

@Inherited – 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类)

从Java 7开始,额外添加了3个注解:

@SafeVarargs – Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

@FunctionalInterface – Java 8开始支持,标识一个匿名函数或函数式接口。

@Repeatable – Java 8开始支持,标识某注解可以在同一个声明上使用多次。

元注解

元注解就是上面说到的作用在其他注解上的注解。

@Retention:表明该注解的生命周期

生命周期类型

描述

RetentionPolicy.SOURCE

标记的注释仅保留在源级别中,并由编译器忽略。

RetentionPolicy.CLASS

标记的注释在编译时由编译器保留,但Java虚拟机(JVM)会忽略。

RetentionPolicy.RUNTIME

标记的注释由JVM保留,因此运行时环境可以使用它。

@Documented:表明该注解标记的元素可以被Javadoc或类似的工具文档化

@Target: 表明该注解可以应用的java元素类型

Target类型

描述

ElementType.TYPE

可以应用于类的任何元素。

ElementType.FIELD

可以应用于字段或属性。

ElementType.METHOD

可以应用于方法级注释。

ElementType.PARAMETER

可以应用于方法的参数。

ElementType.CONSTRUCTOR

可以应用于构造函数。

ElementType.LOCAL_VARIABLE

可以应用于局部变量。

ElementType.ANNOTATION_TYPE

可以应用于注释类型。

ElementType.PACKAGE

可以应用于包声明。

ElementType.TYPE_PARAMETER

1.8版本新增,应用于类型变量

ElementType.TYPE_USE

1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

@Inherited:表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解

@Repeatable:Java SE 8中引入的,@Repeatable注释表明标记的注释可以多次应用于相同的声明或类型使用(即可以重复在同一个类、方法、属性等上使用)。

自定义注解

其实说了这么多,都是一些总结性的知识点,我敢说到现在,大家还是对注解是云里雾里的。想要更好的认识注解,只有我们自己定义一个注解,来实现一个我们的注解,通过实现一个我们自己的注解来熟悉注解的工作流程。

Java中自定义注解和创建一个接口相似,声明一个注解要用到以下东西:

修饰符:访问修饰符必须为public,不写默认为pubic;

关键字:关键字为@interface;

注解名称:注解名称为自定义注解的名称,使用时还会用到;

注解类型元素:注解类型元素是注解中内容,可以理解成自定义接口的实现部分。

同时需要注意以下事项:

注解方法不能有参数;

注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组;

注解方法可以包含默认值;

注解可以包含与其绑定的元注解,元注解为注解提供信息。

规则知道了,下面我来编码实现一个自定义的注解。比如我们在实现一个自定义的ORM框架的时候,都会通过注解来实现数据表名与JAVA类的映射,表字段与JAVA类字段的映射关系,下面就来简单实现这个功能。

定义Table注解:

package com.jellythink.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(value={ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface Table {

String value();

}

定义字段注解:

package com.jellythink.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(value={ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

public @interface FieldMapping {

String name();

String type();

int length();

}

应用注解:

package com.jellythink;

import com.jellythink.annotation.FieldMapping;

import com.jellythink.annotation.Table;

@Table("tb_student")

public class Student {

@FieldMapping(name = "id", type = "int", length = 10)

private int id;

@FieldMapping(name = "name", type = "varchar", length = 6)

private String stuName;

@FieldMapping(name = "age", type="int", length = 4)

private String stuAge;

// 省略getter and setter

}

读取注解信息:

package com.jellythink;

import com.jellythink.annotation.Table;

import com.jellythink.annotation.FieldMapping;

import java.lang.reflect.Field;

public class Main {

public static void main(String[] args) {

try {

Class clazz = Class.forName("com.jellythink.Student");

// 查询类上的注解

Table tbStudent = (Table)clazz.getAnnotation(Table.class);

System.out.println(tbStudent.value());

// 查询属性上的注解

Field stuId = clazz.getDeclaredField("id");

FieldMapping fieldStuId = stuId.getAnnotation(FieldMapping.class);

System.out.println(fieldStuId.name() + "--" + fieldStuId.type() + "--" + fieldStuId.length());

Field stuName = clazz.getDeclaredField("stuName");

FieldMapping fieldStuName =

stuName.getAnnotation(FieldMapping.class);

System.out.println(fieldStuName.name() + "--" + fieldStuName.type() + "--" + fieldStuName.length());

Field stuAge = clazz.getDeclaredField("stuAge");

FieldMapping fieldStuAge =

stuName.getAnnotation(FieldMapping.class);

System.out.println(fieldStuAge.name() + "--" + fieldStuAge.type() + "--" + fieldStuAge.length());

// 通过上面查询到的数据拼接成SQL语句

String name = "果冻";

String sql =

"select * from " + tbStudent.value() + " where " + fieldStuName.name() + " = '" + name + "'";

System.out.println("SQL=" + sql);

} catch (Exception e) {

// Handle the exception

}

}

}

通过上面的代码,有木有感受到自定义注解还是非常简单的;同时有没有感觉到注解这个功能是非常强大的。

总结

总的来说,注解这个功能很强大,但是使用起来确是非常简单的,这就是牛叉东西的特点,好用又让人不感觉到复杂。以后再遇到注解东西,内心就不再犯怵,不再迷茫了。

果冻想,认真玩技术的地方。

2020年10月20日,于内蒙古呼和浩特。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值