Java注解annotation
1.什么是注解
1.从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,
2.可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。
3.通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
2.内置注解
@Override:重写的注解
作用范围:该注解只适用于修饰方法,表示一个方法声明打算重写父类中的另一个方法声明。
查看源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Deprecated :已经废弃的注解,不推荐使用
**作用范围:**该注解可以用于修饰方法,属性,类,表示不鼓励程序员使用这样的元素,通常是
因为它很危险或者存在更好的解决办法。
查看源码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@SuppressWarnings:代码提示警告的注解
**作用范围:**用于抵制编译时的警告信息,与前两个注解不同,需要添加一个参数才能正确使用注解,
这些参数都是已经定义好了的。
使用格式:
@SuppressWarnings(“”)
@SuppressWarnings({})
@SuppressWarnings(value={})
参数的作用
@SuppressWarnings(“unchecked”):告诉编译器忽略 unchecked 警告信息
@SuppressWarnings(“serial”) :如果编译器出现这样的警告信息
@SuppressWarnings(“unchecked”, “deprecation”) :告诉编译器同时忽略unchecked和deprecation的警告信息
@SuppressWarnings(value={“unchecked”, “deprecation”})等同于@SuppressWarnings(“unchecked”, “deprecation”)
查看源码
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value(); //value 表示默认参数
}
真实代码案例
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 注解有检查和约束性,确保代码的规范性
* 内置注解:
* @Override 重写的注解
* @author jkl
*@SuppressWarnings :监控注解:可以作用在类,方法,变量,字段上
*/
public class Test01 extends Object{
@Override
public String toString(){
return super.toString();
}
//废弃注解,已经不适用了
@Deprecated
public void test(){
}
@SuppressWarnings("all")
@Deprecated
private String name;
@SuppressWarnings("all")
public void test02(){
List list = new ArrayList<>();
}
public void test03(){
@SuppressWarnings("unused")
HashMap<String , Object> map = new HashMap<String,Object>();
}
}
3.元注解
元注解的作用:
1.负责注解其他注解,Java定义了4个标准的mete-annotation类型,他们被用来提供对
其他注解类型做声明。
2.这些类型和他们所支持的的类在java.lang.annotation包中可以找到。
1.@Target目标注解
**作用范围:**用于描述注解的使用范围: 如作用在类,方法,字段上等
2.@Retention用于描述注解的使用范围
作用范围:
表示需要在什么级别保存该注解信息,用于描述注解的使用范围: 如作用在类,方法,字段上等。
作用范围大小:SOURCE<CLASS<RUNTIME
3.@Inherited 继承父类注解
作用范围:
说明子类可以继承父类的注解
4.@Documented
**作用:**说明该注解讲被包含在javadoc中
5.元注解源码分析
查看@Target注解源码
@Documented
@Retention(RetentionPolicy.RUNTIME) //表示在运行时起作用
@Target(ElementType.ANNOTATION_TYPE) // 表作用在注解类上
public @interface Target {
ElementType[] value(); //value 表示参数而不是方法
}
ElementType类源码
ElementType是一个枚举类
public enum ElementType {
TYPE, /**表示作用在类上 */
FIELD, /** 表示作用在字段上 */
METHOD, /** 表示作用在方法上 */
PARAMETER, /** 表示作用在参数上 */
CONSTRUCTOR, /** 表示作用在构造器上 */
LOCAL_VARIABLE,
ANNOTATION_TYPE, /** 表示作用在参数上 */
PACKAGE, /** 表示作用在包名上 */
TYPE_PARAMETER,
TYPE_USE
}
查看@Retention注解源码
@Documented
@Retention(RetentionPolicy.RUNTIME)//表示在运行时起作用
@Target(ElementType.ANNOTATION_TYPE)// 表作用在注解类上
public @interface Retention {
RetentionPolicy value(); // value 表示参数而不是方法
}
RetentionPolicy类源码
RetentionPolicy是一个枚举类
public enum RetentionPolicy {
SOURCE, /** 表示在源码上运行 */
CLASS, /** 表示在.class文件中运行 */
RUNTIME /** 在程序启动时运行 */
}
6.元注解总结:
重要注解@Retention,@Target,重要的类ElementType,RetentionPolicy
4.自定义注解
1.使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口
分析
@interface用来声明一个注解,格式:public @interface 注解名称 {定义内容}
其中的每个方法实际上是声明了一个参数。
方法的名称就是参数名称
返回值类型就是参数类型(返回值只能是基本类型Class,Stirng,enum,int)
可以通过default来声明一个参数的默认值。
如果只有一个参数的成员,一般参数名为value.
元注解必须有值,我们定义元注解时,经常使用空字符串,0作为默认值。
4.1自定义一个注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented //说明该注解讲被包含在javadoc中
@Inherited //说明子类可以继承父类的注解
@Target({ElementType.TYPE , ElementType.METHOD})//用于描述注解的使用范围: 如作用在类,方法,字段上等
/**
* @Retention : 用于描述注解的生命周期
* SOURCE:表示在源码上运行,
* CLASS表示在.class中运行
* RUNTIME:在程序启动时运行
* SOURCE<CLASS<RUNTIME
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
String name() default "";
int age() default -1 ;//默认值等于-1,表示不存在
String [] arry() default "{1,2}";//定义数组
}
4.2自定义注解模拟真实开发案例
1.创建controller注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* controller控制类注解
* @author jkl
*@Target 作用在类(TYPE)和方法上(METHOD)
*@Retention : RUNTIME 程序运行时有效
*
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiControl {
String value () default ""; //controller名称
String name () default ""; // controller名称
}
2.创建作用在方法上的注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* method控制层方法注解
* @author jkl
*自定义方法注解:作用在类和方法上
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiOperation {
String value () default "";
String name () default "";
String method () default "";
}
3.创建作用在实体类注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* entity实体类注解
* @author jkl
*@Target:只能作用在字段上
*@Retention:作用在源码上
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface ApiModelProperty {
String value () default ""; //字段默认值
String field () default ""; //字段名称
String type () default ""; //字段类型
String comment () default ""; //字段描述
int length () default 11 ; // 字段长度
}
4.创建在表上的注解
package com.gun.annotation.apioperation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Table表注解
* @author jkl
*@Target 只能作用在类上
*@Retention 运行时起作用
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiTableId {
String value () default ""; //表英文名称
String name () default ""; // 表中文名称
}
案例1:使用创建的注解作用在实体类上
package com.gun.annotation.pojo;
import com.gun.annotation.apioperation.ApiModelProperty;
import com.gun.annotation.apioperation.ApiTableId;
@ApiTableId(value="t_users" ,name="用户管理表")
public class Users {
@ApiModelProperty(value="1",field="u_id",type="int",length =11, comment="主键ID")
private int id;
@ApiModelProperty(field="u_name",type="varchar",length =10, comment="用户名称")
private String name;
@ApiModelProperty(field="u_age",type="int", length =4, comment="用户年龄")
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
案例2:使用创建注解作用在controller上
package com.gun.annotation.controller;
import com.gun.annotation.apioperation.ApiControl;
import com.gun.annotation.apioperation.ApiOperation;
/**
* 注解作用在类上
* @author jkl
*
*/
@ApiControl(value="user",name="用户管理")
public class UserController {
@ApiOperation(value ="ROLE_UPDATE_USER",name = "用户修改",method="updateUser")
public void updateUser(){
}
@ApiOperation(value ="ROLE_ADD_USER",name = "用户修改",method="addUser")
public void addUser(){
}
}
5.扩展
验证@Inherited注解是一个继承注解
1、创建父类Father类
package com.gun.annotation.inherited;
/**
* 父类
* @author jkl
*
*/
//@HasInerited
@NotInherited
public class Father {
public void addFacher(){
System.out.println("父类添加方法----");
}
public void updateFacher(){
System.out.println("父类编辑方法----");
}
}
2.创建子类Child
package com.gun.annotation.inherited;
/**
* 子类
* @author jkl
*
*/
public class Child extends Father {
}
3.自定义一个注解包含@iInherited
package com.gun.annotation.inherited;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 包含@inerited注解
* @author jkl
*
*/
@Inherited // 子类继承父类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HasInherited {
String value () default "";
String name () default "";
}
4.自定义一个注解不包含@Inherited
package com.gun.annotation.inherited;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 未包含@inerited注解
* @author jkl
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotInherited {
String value () default "";
int lenth () default -1 ;
}
5.测试结果
package com.gun.annotation.inherited;
import java.lang.annotation.Annotation;
/**
* @author jkl
*总结:被@Inherited注解修饰的注解,如果作用于某个类上,其子类是可以继承的该注解的。
*反之,如果一个注解没有被@Inherited注解修饰,那么它的的作用范围只能在当前类上,其子类是不能被继承的。
*
*/
public class Test {
public static void main(String[] args) {
Annotation [] ann = Father.class.getAnnotations();
System.out.println("------- 父类 Father 信息 --------");
System.out.println("父类注解个数:" + ann.length);
for(Annotation anno : ann){
String name = anno.annotationType().getName();
String simpleName = anno.annotationType().getSimpleName();
System.out.println("获取注解的包名:"+name);
System.out.println("获取注解的类名:"+simpleName);
}
System.out.println("------- 子类 child 信息 --------");
Annotation [] child =Child.class.getAnnotations();
System.out.println("子类注解长度:"+child.length);
for(Annotation zi : child){
String ziSimpleName = zi.annotationType().getSimpleName();
System.out.println("获取子类注解名称:"+ziSimpleName);
}
}
}
5.1父类Father包含@Inherited注解输出结果:
------- 父类 Father 信息 -------- 父类注解个数:1 获取注解的包名:com.gun.annotation.inherited.HasInherited 获取注解的类名:HasInherited ------- 子类 child 信息 -------- 子类注解长度:1 获取子类注解名称:HasInherited |
---|
5.2.父类Father不包含@Inherited注解输出结果:
------- 父类 Father 信息 -------- 父类注解个数:1 获取注解的包名:com.gun.annotation.inherited.HasInherited 获取注解的类名:HasInherited ------- 子类 child 信息 -------- 子类注解长度:0 获取子类注解名称:HasInherited |
---|
}
5.1父类Father包含@Inherited注解输出结果:
| ------- 父类 Father 信息 --------<br/>父类注解个数:1<br/>获取注解的包名:com.gun.annotation.inherited.HasInherited<br/>获取注解的类名:HasInherited<br/>------- 子类 child 信息 --------<br/>子类注解长度:1<br/>获取子类注解名称:HasInherited |
| ------------------------------------------------------------ |
5.2.父类Father不包含@Inherited注解输出结果:
| ------- 父类 Father 信息 --------<br/>父类注解个数:1<br/>获取注解的包名:com.gun.annotation.inherited.HasInherited<br/>获取注解的类名:HasInherited<br/>------- 子类 child 信息 --------<br/>子类注解长度:0<br/>获取子类注解名称:HasInherited |
| ------------------------------------------------------------ |