1.注解的定义
Java注解又称Java标注,是在 JDK5 时引入的新特性,注解(也被称为元数据)。
Java注解它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
2.注解与注释的区别
注解是对代码的解释和说明,其目的是提高程序代码的可读性。注解是可以被编译器打包进入class文件。
注释只存在于java源代码中,对于编译和运行没有任何作用,也不会被编译到class文件中。注释是给程序员看的,编译器与JVM都不需要知道它。
3.注解的应用
1.生成文档这是最常见的,也是java 最早提供的注解;
2.在编译时进行格式检查,如@Override放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出;
3.跟踪代码依赖性,实现替代配置文件功能,比较常见的是spring 2.5 开始的基于注解配置,作用就是减少配置;
4.在反射的 Class, Method, Field 等函数中,有许多于 Annotation 相关的接口,可以在反射中解析并使用 Annotation。
4.注解的分类
标准注解
1.常用的三种:
//@Override 重写的注解 @Override public String toString() { return super.toString(); } //@Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方法 @Deprecated public static void test1() { System.out.println("Deprecated"); } //@SuppressWarnings("关键字") 镇压警告(不推荐使用),将警告消除 @SuppressWarnings("all") public void test2() { List list = new ArrayList(); } public static void main(String[] args) { test1(); }
关键字 | 被抑制的警告类型 |
---|---|
all | 抑制所有警告 |
deprecation | 抑制使用了过时的类或方法的警告 |
fallthrough | 抑制switch块中没有break语句的警告 |
finally | 抑制finally块中不能正常完成的警告 |
rawtypes | 抑制没有使用泛型的警告 |
serial | 抑制可序列化类没有使用序列化ID的警告 |
unchecked | 抑制未检查操作的警告 |
2.函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。(附加)
元注解
1.Target
枚举值 | 注解能够被应用的地方 |
---|---|
ElementType.ANNOTATION_TYPE | 注解类型的声明 |
ElementType.CONSTRUCTOR | 构造方法的声明 |
ElementType.FIELD | 属性的声明 |
ElementType.LOCAL_VARIABLE | 局部变量的声明 |
ElementType.METHOD | 方法的声明 |
ElementType.PACKAGE | 包的声明 |
ElementType.PARAMETER | 方法参数的声明 |
ElementType.TYPE | 类,接口以及枚举的声明 |
2.Retention
3.Documented
4.Inherited
code:
@MyAnnotation public class test02 { @MyAnnotation public void test02() { } } //自定义一个简单的注解 //@Target 表示我们的注解可以用在哪些地方 //@Retention 表示我们的注解在什么地方有效 //@Documented 表示是否将我们的注解生成在Javadoc中 //@Inherited 表示子类可以继承父类的注解 @Target(value = {ElementType.METHOD, ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) @Documented @Inherited @interface MyAnnotation{ }
自定义注解
自定义注解的格式
// 元注解 public @interface 注解名称{ // 属性列表 }
示例:
//自定义注解 public class test03 { //注解可以显示赋值, 如果没有默认值,我们就必须给注解赋值 //注解参数的顺序随意 @MyAnnotation2(age = 18, name = "jacky") public void test() { } @MyAnnotation3("jacky") public void test2() { } } @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //注解的参数: 参数类型 + 参数名 + (); String name() default ""; int age() default 0; int id() default -1; String[] schools() default {"peking university"}; } @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ //如果注解参数为value赋值时可以直接写值 String value(); }
5.获取泛型信息
Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。
public static void main(String[] args) throws NoSuchMethodException { Method method = test08.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for(Type genericParameterType : genericParameterTypes) { System.out.println("#" + genericParameterType); if(genericParameterType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for(Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } Method method2 = test08.class.getMethod("test02", null); Type genericReturnType = method2.getGenericReturnType(); if(genericReturnType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for(Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } public void test01(Map<String, User> map, List<User> list) { } public Map<String, User> test02() { return null; } `
6.获取注解信息
ORM Object Relationship Map —> 对象关系映射 例如 数据库中表与代码中对应的类的映射 属性与字段对应 对象与记录对应
package cn.com.reflection; import java.io.File; import java.lang.annotation.*; import java.lang.reflect.Field; //练习反射操作注解 public class test09 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("cn.com.reflection.test09.Student"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解value的值 Table annotation = (Table)c1.getAnnotation(Table.class); String value = annotation.value(); System.out.println(value); //获得类指定的注解 Field name = c1.getDeclaredField("name"); Field1 annotation1 = name.getAnnotation(Field1.class); System.out.println(annotation1.columnName()); System.out.println(annotation1.type()); System.out.println(annotation1.length()); } } @Table("db_student") class Student { @Field1(columnName = "db_id", type = "int", length = 10) private int id; @Field1(columnName = "db_age", type = "int", length = 10) private int age; @Field1(columnName = "db_name", type = "varchar", length = 3) private String name; @Override public String toString() { return "Student{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Table { String value(); } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Field1{ String columnName(); String type(); int length(); }