注解:
Java5开始 Java支持对元数据的支持, 就是是Annotation(注解)
元数据: metadata描述数据的数据
注解:标签 Annotation
所有的Annotation都是java.Lang.annotation.Annotation接口的子接口
所有Annotation是一种特殊的接口
回顾注解:
@Override -->重写
@Deprecated --> 过时的
@SuppressWarings --> 压制警告
既可以放在方法上,放在变量上,放在类或接口上
使用注解需要注意:必须有三个参与才有意义
1.有注解的本身
2.被放置的位置(类,属性,方法,接口,参数上,包等等)
3.由第三方程序使用反射的手段赋予注解特殊的功能
Java5之前自带注解
Java5中提供的
@Override --> 限定子类重写父类的方法,只能在方法上
@Deprecated --> 标记当前方法已经过时,不推荐使用 只能用在方法上
@SuppressWarings --> 抑制编译器发出多种警告
@SuppressWarings(value=“all”) 可以应用在方法,类,属性上
Java7中提供了一个
@SafeVarargs 抑制堆污染
当方法使用可变参数和泛型参数,此时就会造成堆污染 Arrays.asList
Java8中提供一个
@FunctionalInteFace 函数式编程 -->所用在接口上
元注解:
描述注解的注解,用来限定注解可以贴在哪些程序元素上,还可以指定注解存在的周期
@Retention: 表示注解可以保存在哪一个代码时期. 保存的时期的值,封装在RetentionPolicy枚举类中:
注意:一般的,自定义的注解,使用RUNTIME.(使用反射赋予注解功能)
SOUECE:注解只能存在于源文件中,一旦编译,在字节码中就消失了.
CLASS:(缺省),注解可以存在于源文件和字节码文件中,一旦加载进JVM,在JVM中就消失了.
RUNTIME:注解可以存在于源文件,字节码文件,JVM中.
@Target:表示注解可以贴在哪些位置(类,方法上,构造器上等等).
位置的常量封装在ElementType枚举类中:
ElementType.ANNOTATION_TYPE只能修饰Annotation
ElementType.CONSTRUCTOR只能修饰构造方法
ElementType.FIELD只能修饰字段(属性),包括枚举常量
ElementType.LOCAL_VARIABLE只能修饰局部变量
ElementType.METHOD只能修饰方法
ElementType.PACKAGE只能修饰包(极少使用)
ElementType.PARAMETER只能修饰参数
ElementType.TYPE只能修饰类,接口,枚举
自定义注解:
语法格式:
@interface
@Retention(设置注解存储在的时间)
@Target(设置可以书写注解的位置)
public @interface 注解名{
注解中的成员:
抽象方法 --> (属性)
数据类型 方法名() default 默认值;
}
使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
**定义注解格式:**public @interface 注解名 {定义体}
注解参数的可支持数据类型:
- 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
- String类型
- Class类型
- enum类型
- Annotation类型
- 以上所有类型的数组
参数定义要点:
- 只能用public或默认(default)这两个访问权修饰;
- 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组;
- 如果只有一个参数成员,建议参数名称设为value();
- 注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或负数作为默认值是一种常用的做法。
ps:Spring框架中–> 注解最多 --> 动态代理模式 --> 内省模式JavaBean和Map互转
实例:
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.sql.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface testInter12 {
String value1 () default "abc";
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface testInter11 {
String value () default "abc";
}
@testInter12(value1="ok")
public class demo8 {
public static void main(String[] args) throws ClassNotFoundException, SQLException, NoSuchMethodException {
Class<?> class1 = Class.forName("demo8");
//获取方法的字节码文件对象
Method method = class1.getMethod("show");
//判断后面的注解是否在当前的类上
if (class1.isAnnotationPresent(testInter12.class)) {
//获取注解
testInter12 a1 = (testInter12) class1.getAnnotation(testInter12.class);
System.out.println("类上的value:"+a1.value1());
}
//判断后面的注解是否在当前的方法上
if (method.isAnnotationPresent(testInter11.class)) {
testInter11 t1 = method.getAnnotation(testInter11.class);
System.out.println("方法上的注解:"+t1.value());
}
}
@testInter11
public void show(){
System.out.println("haha");
}
}
注解的作用:
java 注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解析注解 来使用这些数据),常见的作用有以下几种:
1.生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等;
2.跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量;
3.在编译时进行格式检查。如@Override放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出;
4.自定义注解:可以应用到反射中,如实现实体类某些属性不自动赋值,或者验证某个对象属性完整性等