赞
踩
路径
注解
什么是注解?
注解:就是具有特殊含义的标记(注解是给机器阅读的)
注解的作用
注解就是在代码里添加一些特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行操作
注解的作用:
编译检查:
代码分析:
通过代码里标识的注解对代码进行分析
框架的配置( 框架 = 代码 + 配置 )
生成帮助文档:
@author:用来标识作者姓名
@version:用于标识对象的版本号,适用范围:文件、类、方法
使用@author和@version注解就是告诉Javadoc工具在生成帮助文档时把作者姓名和版本号也标记在文档中
使用过的注解:
小结
注解:在代码中添加的标记,JVM看到注解标记后会执行一些操作
注解的作用:
路径
注解的定义格式
定义注解使用关键字:@interface
public @interface 注解名{
//内容
}
注解本质上就是一个接口。所有注解都会继承一个接口:Annotation
public interface 自定义注解名 extends java.lang.annotation.Annotation {}
带有属性的注解
属性的格式
属性定义示例
public @interface Student {
String name(); // 姓名
int age() default 18; // 年龄
String gender() default "男"; // 性别
}
// 该注解就有了三个属性:name,age,gender
属性适用的数据类型【记住】
1. 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
2. String,Class,注解类型,枚举类
3. 以上类型的一维数组形式
小结
注解的定义格式:
public @interface 注解名
{
//属性格式 : 数据类型 属性名()
String 属性名();
int 属性名() default 默认值;
}
//注意:属性的类型只能是8种基本数据类型、String、Class、枚举、注解、(以及一维数组形式)
路径
注解的使用格式
格式:
//无属性注解
@注解名 例:@Test
//有属性注解
@注解名(属性=值,属性=值)
注解可以在类上,成员变量上,构造方法上,方法上,参数上…
有默认值的属性,可以不用进行赋值。
案例代码
将Book注解使用起来
public @interface Book {
String name();
double price() default 100.0;
String[] author();
}
建立一个BookStore的类,在类中定义成员变量,构造方法,成员方法
@Book(name = "西游记", author = {"吴承恩", "张三"}) public class BookStore { @Book(name = "三国", price = 10, author = {"罗贯中"}) private String book; @Book(name = "三国", price = 10, author = {"罗贯中"}) public BookStore() { } @Book(name = "三国", price = 10, author = {"罗贯中"}) public void test() { } }
特殊属性value
如果注解中只有一个属性要赋值,而且名字是value,可以将value给省略,可以直接给值
@interface A{ String value(); } @interface B{ String value(); String name(); } @interface C{ String value(); int price() default 100; //有默认值 } //测试类 public class Demo { @A("值") //当自定义注解中仅有一个value属性时,可以省略value属性名 public void test1() { } @B(value = "值",name="aa") //当自定义注解中除了value属性外,还有其它属性,value不能省略 public void test2() { } @C("值")//自定义注解中除了value属性外,还有其它带有默认值的属性,value可以省略 public void test3() { } }
小结
自定义注解:
public @interface Book{
//属性
String name();
double price() default 100;
}
在程序代码中使用自定义注解:
//注解可以应用在:类、方法、变量、构造方法
@Book(name="属性值") //price属性使用默认值
public class BookStore{
@Book(name="属性值",price="新的值") //新的price值,会覆盖默认值
public void method(){
}
}
1.如果自定义注解中的属性不给默认值,那么使用的时候必须赋值,如果有默认值,使用的时候可以不给值
2.使用注解:@注解名(属性名=属性值,属性名=属性值,....)
3.如果注解中没有属性,使用的时候@注解名
4.如果属性是数组,那么赋值方式:
@注解名(属性名=属性值,属性名=属性值,属性名={属性值,属性值,..}....)
5.如果属性是数组类型,并且使用的时候只给一个值,那么可以省略大括号
6.如果属性只有一个并且属性名是value,那么给value赋值的时候可以不写value
7.如果含有多个属性,并且没有默认值,那么给value赋值的时候必须书写value
8.如果含有多个属性,并且具有默认值,那么给value赋值的时候可以不写value
9.同一个注解不能同时修饰同一个方法或者同一个类
10.不同注解可以同时修饰同一个方法或者同一个类
路径
元注解的作用
默认情况下,注解可以用在任何地方,比如类,成员方法,构造方法,成员变量等地方
如果要限制自定义注解的使用位置怎么办?那就要学习一个新的知识点:元注解
结论:元注解是用来约束自定义注解的使用范围、生命周期
常用的元注解
常用元注解:@Target、@Retention
@Target
@Retention
元注解的使用
@Target({ElementType.METHOD,ElementType.TYPE}) //元注解 @interface Stu{ String name(); } //类 @Stu(name="jack") //成功 public class AnnotationDemo02 { // 成员变量 @Stu(name = "lily") // 编译失败 private String gender; // 成员方法 @Stu(name="rose") //成功 public void test(){ } // 构造方法 @Stu(name="lucy") // 编译失败 public AnnotationDemo02(){} }
小结
元注解的作用:
路径
获取注解数据的原理
想要对注解中的数据进行解析,需要借助:AnnotatedElement接口
AnnotatedElement 是一个接口,定义了解析注解的方法:
1. boolean isAnnotationPresent(Class<Annotation> annotationClass) 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false public class BookStore{ @Book(name="书名") public void buy() // Method对象 判断该对象上是否使用了@Book注解 { // boolean flag = Method对象.isAnnotationPresent(Book.class) } } 2. T getAnnotation(Class<T> annotationClass) 根据注解类型获得对应注解对象 // 获取对象上的自定义注解 // Book bookAnno = Method对象.getAnnotation(Book.class); // bookAnno.属性 //获取注解中属性的值
Class,Constructor,Method,Field都会实现AnnotatedElement 接口
注解解析的步骤:(注解是书写在:类、方法、变量上)
1、利用反射技术获取注解作用的对象:类、方法、变量、构造方法
2、判断对象上是否有自定义注解存在
3、有:获取对象上的自定义注解
4、使用获取到的自定义注解对象,拿到注解中的属性值
注意:注解解析必须保证自定义注解生命周期在RUNTIME(程序运行中)
案例代码
需求如下:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) //使用范围:方法、类 @Retention(RetentionPolicy.RUNTIME) //保证注解在程序执行时有效(适用于注解解析) public @interface Book { String value(); double price() default 100; String[] authors(); } //类 public class BookStore { @Book(value = "Java入门", authors = {"张老师", "毕老师"}) public void buy() { System.out.println("购书....."); } } //对注解中的数据进行解析 public class TestBookStore { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //反射套路:1、Class 2、构造器 3、Method Class<BookStore> bookStoreClass = BookStore.class; //获取构造器 Constructor<BookStore> con = bookStoreClass.getConstructor(); BookStore bookStore = con.newInstance();//实例化对象 //获取Method Method method = bookStoreClass.getMethod("buy"); //解析注解的步骤 if(method.isAnnotationPresent(Book.class)){ //获取Method对象上的Book注解 Book bookAnno = method.getAnnotation(Book.class); //获取注解上的数据 String bookName = bookAnno.value(); double bookPrice = bookAnno.price(); String[] bookAuthors = bookAnno.authors(); System.out.println("书名:"+bookName); System.out.println("价格:"+bookPrice); System.out.println("作者:"+ Arrays.toString(bookAuthors)); } } }
小结
注解解析的步骤:
注解扩展小示例:
public class Student{
private String name;//姓名
private int age;//年龄
private String gender;//性别
private double score;//成绩
private String id;//学号
}
数据:
张三,20,男,90,it1001
利用注解+反射,给Student类中的成员变量赋值
//自定义注解
public @interface Entity{
String value;
}
//Student类
public class Student{
@Entity(value="张三")
private String name;//姓名
@Entiry(value="20")
private int age;//年龄
private String gender;//性别
private double score;//成绩
private String id;//学号
}
目标
路径
需求
需求:模拟Junit测试的@Test
案例分析
案例代码
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //自定义注解 @Target(ElementType.METHOD)//仅能应用在方法上 @Retention(RetentionPolicy.RUNTIME)//生命周期 :运行时 public @interface MyTest { //无属性注解 } public class TestAnnotationParse { //方法1 @MyTest public void method1(){ System.out.println("我是方法1"); } @MyTest public void method3(){ System.out.println("我是方法3"); } public void method2(){ System.out.println("我是方法2"); } } public class Test { public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException { //获取Class对象 Class<TestAnnotationParse> testAnnotationParseClass = TestAnnotationParse.class; //获取Class对象中,所有的Method方法 Method[] methods = testAnnotationParseClass.getMethods(); //遍历数组 for (int i = 0; i < methods.length; i++) { //获取每一个Method对象 Method method = methods[i]; //判断Method对象上,是否存在@MyTest if(method.isAnnotationPresent(MyTest.class)){ method.invoke(testAnnotationParseClass.newInstance()); } } } }
小结
注解解析的步骤:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。