Java 注解(入门篇) 内置注解 元注解 自定义注解

一、为什么要学习注解和反射?

请结合反射学习点击跳转

  1. 注解和反射是我们所有框架的底层(比如 Springboot,Spring)

二、注释(Comments)和注解(Annotation)的区别?

  1. 注释是给程序员理解代码的,程序并不会去编译或者解析
  2. 注解不仅可以给人看还可以给程序看。

三、注解入门

1.注解的格式

@+注解名字
在这里插入图片描述

2.注解3种作用

  1. 文档:中生成注释 比如**@return,**
  2. 检查:作用(比如Override检查函数名称是否一致)
  3. 代码分析:通过反射
    在这里插入图片描述
    在这里插入图片描述

3. 注解(Annotation)的是用区域:

  1. 方法method上比如 Override
  2. 类class
  3. 包 package
  4. 字段
    几乎无所不在。

四、内置注解

1. Override 重写

2. Deprecated 不推荐使用 ,一般是过时的,有危险的,有更好的替代方案的方法或者类.

在这里插入图片描述
在这里插入图片描述

3. SuppressWarnings(“parameter”) parameter 是参数,用来抑制警告信息,

  1. @SuppressWarning(“all”) 抑制所有警告信息
  2. @SuppressWarninig(“unchecked”)
  3. @suppressWarning(value = {“unchecked”,“deprecation”})

  4. 在这里插入图片描述
    在这里插入图片描述

五、元注解

1. 作用

  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. 自定义注解的格式

  1. 元注解
  2. @interface Target(注解名){
  3. 注解需要的参数
    在这里插入图片描述

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:
在这里插入图片描述
在这里插入图片描述

原创文章 132 获赞 11 访问量 4688

猜你喜欢

转载自blog.csdn.net/jarvan5/article/details/106093259