一、为什么要学习注解和反射?
请结合反射学习点击跳转
- 注解和反射是我们所有框架的底层(比如 Springboot,Spring)
二、注释(Comments)和注解(Annotation)的区别?
- 注释是给程序员理解代码的,程序并不会去编译或者解析
- 注解不仅可以给人看还可以给程序看。
三、注解入门
1.注解的格式
@+注解名字
2.注解3种作用
- 文档:中生成注释 比如**@return,**
- 检查:作用(比如Override检查函数名称是否一致)
- 代码分析:通过反射
3. 注解(Annotation)的是用区域:
- 方法method上比如 Override
- 类class
- 包 package
- 字段
几乎无所不在。
四、内置注解
1. Override 重写
2. Deprecated 不推荐使用 ,一般是过时的,有危险的,有更好的替代方案的方法或者类.
3. SuppressWarnings(“parameter”) parameter 是参数,用来抑制警告信息,
- @SuppressWarning(“all”) 抑制所有警告信息
- @SuppressWarninig(“unchecked”)
- @suppressWarning(value = {“unchecked”,“deprecation”})
- …
五、元注解
1. 作用
- 元注解的作用就是解释其他注解的注解
2. Java定义了4个标准的元注解
1.@Target : 描述注解的使用范围
2.@Retention,保留期,生命周期,描述注解的生命周期
(source<Class<Runtime)一般使用Runtime最大生命周期,
3.Document : 文档,说明该注解包含在Javadoc 中
4.Inherited : 继承,说明子类可以继承父类的该注解。
六、元注解注解详解
1.@Target(value = {ElementType.METHOD,ElementType.FIELD})
1.看需要什么参数
(1)
(2)
(3)我们选择方法METHOD和字段FIELD
(4)
(5)可以用在方法和字段上.
(6)总结
2. @Retention (value = RetentionPolicy.RUNTIME)
3. @Documented
//3.是否将注解生成在Javadoc
4.@Inherited
//子类可以继承父类的注解
七、自定义注解 @interface
这个案例要用到反射知识(入门)
1. 自定义注解的格式
- 元注解
- @interface Target(注解名){
- 注解需要的参数
2.步骤
* 一、自定义注解:@interface自动继承 java.lang.annotation.Annotation 接口.
* 1. 添加几乎固定的元注解
* @Target(value = {ElementType.TYPE,ElementType.METHOD})//最常用类和方法可用
* @Retention(value = RetentionPolicy.RUNTIME)//最常用的最大生命周期
* 2.添加使用你定义的注解时候的参数(**参数其实就是抽象方法**)
* (1)添加方法. 类型 名称() default 默认值;
* String name() default "";
* (2)没有默认值就使用必须添加参数比如 @Target @Retention
* (3)如果参数只有一个建议命名参数名为 value 这样使用时候可以省略参数名
* (4)数组类型使用参数的注解使用时后传入的参数有大括号包裹{},数组你只传入一个值的时候大括号可以省略比如
@Target(value = {ElementType.TYPE,ElementType.METHOD})//最常用类和方法可用
@Retention(value = RetentionPolicy.RUNTIME)//最常用的最大生命周期
3.示例
package Java学习.Java高级.注解和反射.注解.自定义注解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 一、自定义注解:@interface自动继承 java.lang.annotation.Annotation 接口.
* 1. 添加几乎固定的元注解
* @Target(value = {ElementType.TYPE,ElementType.METHOD})//最常用类和方法可用
* @Retention(value = RetentionPolicy.RUNTIME)//最常用的最大生命周期
* 2.添加使用你定义的注解时候的参数
* (1)添加方法. 类型 名称() default 默认值;
* String name() default "";
* (2)没有默认值就使用必须添加参数比如 @Target @Retention
* (3)如果参数只有一个建议命名参数名为 value 这样使用时候可以省略参数名
*/
public class Demo03 {
@MyAnnotation(name = "王二麻子")
public static void main(String[] args) {
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})//最常用类和方法可用
@Retention(value = RetentionPolicy.RUNTIME)//最常用的最大生命周期
@interface MyAnnotation{
String name() ;
int id() default 0;
String[] friends() default {"张三","李四"};
}
2(3)示例比如Target
八、案例:使用反射解析注解
1. 步骤
* 1. 新建一个注解,参数给一个className和methodName
* 2.添加注解到需要的地方Demo
* 3.获得Demo的demoClass
* 4.demoClass.getAnnotation 新建Annotation对象
* (其实就是 生成注解子类的实现)
//其实就是再内存中生成一个该注解接口的子类实现对象
pbulic class ConfImplements implements Conf{
public String className(){
return "全类名";
}
public String method(){
return "方法名"
}
}
* 5.使用子类实现调用方法获取className 和 methodName
* 6.使用全类名className 和 methodName
* (1)Class.forName(className) 新建Class类对象
* (2)获取Constructor对象和方法 Method
* (3)使用Constructor对象创建新实例对象 Constructor.newInstance()
* (4)执行方法 eat.invoke(newInstance)
2.代码
(1)新建一个注解: Conf.java
package Java学习.Java高级.注解和反射.注解.案例反射解析注解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// * 1. 新建一个注解,参数给一个className和methodName
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Conf {
String className();
String methodName();
}
(2)Person.java
package Java学习.Java高级.注解和反射.注解.案例反射解析注解;
public class Person {
public Person() {
}
public void eat(){
System.out.println("Person: eating...");
}
}
(3)Demo.java
package Java学习.Java高级.注解和反射.注解.案例反射解析注解;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 一、案例:反射解析注解
* 1,要求:
* 二、步骤
* 1. 新建一个注解,参数给一个className和methodName
* 2.添加注解到需要的地方Demo
* 3.获得Demo的demoClass
* 4.demoClass.getAnnotation 新建Annotation对象
* (其实就是 生成注解子类的实现)
* 5.使用子类实现调用方法获取className 和 methodName
* 6.使用全类名className 和 methodName
* (1)Class.forName(className) 新建Class类对象
* (2)获取Constructor对象和方法 Method
* (3)使用Constructor对象创建新实例对象 Constructor.newInstance()
* (4)执行方法 eat.invoke(newInstance)
*/
// * 2.添加注解到需要的地方Demo
@Conf(className = "Java学习.Java高级.注解和反射.注解.案例反射解析注解.Person",methodName = "eat")
public class Demo {
public static void main(String[] args) throws Exception {
// * 3.获得Demo的demoClass
Class<Demo> demoClass = Demo.class;
// * 4.demoClass.getAnnotation 新建Annotation对象
Conf annotation = demoClass.getAnnotation(Conf.class);
//5.使用子类实现调用方法获取className 和 methodName
String className = annotation.className();
String methodName = annotation.methodName();
System.out.println(className);
System.out.println(methodName);
//6.
Class<?> aClass = Class.forName(className);
Constructor<?> constructor = aClass.getConstructor();
Object newInstance = constructor.newInstance();
Method eatMethod = aClass.getMethod("eat");
eatMethod.invoke(newInstance);
}
}
九、案例2:注解和反射的测试框架搭建
1. 步骤
* 一、目的:做一个测试框架,包括,测试注解,标记测试的类,和执行测试的类
* 二、步骤
* 1. 定义测试注解类 Check_Annotation.java
* 2. 定义标记测试类,并标记需要测试的方法 Test_Calculator.java
* 3. 执行测试的类,通过反射执行测试方法,并将异常写入流到指定文件
2. 代码
(1) 1. 定义测试注解类 Check_Annotation.java
package Java学习.Java高级.注解和反射.注解.案例2测试框架;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// * 1. 定义测试注解类 Check_Annotation.java
@Target(value = {ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Check_Annotation {
}
(2) * 2. 定义标记测试类,并标记需要测试的方法 Test_Calculator.java
package Java学习.Java高级.注解和反射.注解.案例2测试框架;
// * 2. 定义标记测试类,并标记需要测试的方法 Test_Calculator.java
public class Test_Calculator {
@Check_Annotation
public void addition(){
int x = 1;
int y = 1;
System.out.println(x+y);
}
@Check_Annotation
public void subtraction(){
int x = 1;
int y = 1;
System.out.println(x-y);
}
@Check_Annotation
public void multiplication(){
int x = 1;
int y = 1;
System.out.println(x*y);
}
@Check_Annotation
public void division(){
int x = 1;
int y = 0;
System.out.println(x/y);
}
}
(3) 3. 执行测试的类,通过反射执行测试方法,并将异常写入流到指定文件
package Java学习.Java高级.注解和反射.注解.案例2测试框架;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
/**
* 一、目的:做一个测试框架,包括,测试注解,标记测试的类,和执行测试的类
* 二、步骤
* 1. 定义测试注解类 Check_Annotation.java
* 2. 定义标记测试类,并标记需要测试的方法 Test_Calculator.java
* 3. 执行测试的类,通过反射执行测试方法,并将异常写入流到指定文件
* <p>
* 拓展:快捷键
* iter 快捷键迭代器
*/
public class Demo_BugCheck {
public static void main(String[] args) throws IOException {
Test_Calculator test_calculator = new Test_Calculator();
Class<? extends Test_Calculator> aClass = test_calculator.getClass();
Method[] methods = aClass.getMethods();
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("D:\\Program Files\\JetBrains\\test1\\Lab\\src\\Java学习\\Java高级\\注解和反射\\注解\\案例2测试框架\\Bug.txt", true));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss");
bufferedWriter.write("--------测试时间:" + simpleDateFormat.format(System.currentTimeMillis()) + "------------");
int bugCount = 0;
for (Method method : methods) {
/**
* 这个方法可以判断有注解@Check_Annotation的存在。
*/
if (method.isAnnotationPresent(Check_Annotation.class)) {
try {
method.invoke(test_calculator);
} catch (IllegalAccessException e) {
System.out.println(e.toString());
} catch (InvocationTargetException e) {
/**
* 在catch中将异常输出到指定文件里面.
*/
bugCount++;
bufferedWriter.newLine();
bufferedWriter.write("Bug:" + bugCount);
bufferedWriter.newLine();
bufferedWriter.write("出现异常的方法的名称:" + method.getName());
bufferedWriter.newLine();
bufferedWriter.write("异常的名称:" + e.getClass().getSimpleName());
bufferedWriter.newLine();
System.out.println("异常的原因:" + e.getCause().getMessage());
bufferedWriter.write("异常的原因:" + e.getCause().getMessage());
bufferedWriter.newLine();
}
}
}
bufferedWriter.write("------本次测试Bug个数:" + bugCount + "----------------");
bufferedWriter.newLine();
bufferedWriter.flush();//刷新到内存
bufferedWriter.close();
}
}
Run: