Java 注解 学习笔记

概述

注解:说明程序的,给计算机看的
注释:描述程序的,给程序员看的
在这里插入图片描述
注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件

注解怎么使用?

1、注解使用时的语法格式:@ 注解类型名
2、注解可以出现在类上、属性上、方法上、变量上等。。。注解还可以出现在注解类型上

注重学@Override@Deprecated@Target@Retention这四个注解

JDK内置注解

java提供了5个基本的注解,分别是
1.@Override:确保子类确实重写了父类的方法
@Override这个注解只能注解方法
2.@Deprecated:用于表示某个程序元素类,方法等已过时,当其他程序使用已过时的类,方法时编译器会给出警告
3.@SuppressWarnings:被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告

自定义注解

格式&本质

元注解

public @interface 名称 {
	属性列表;
} 

本质:就是一个接口,该接口默认继承Annotation接口

public interface myAnno extends java.lang.annotation.Annotation {
}

属性定义

我们通常在注解中定义属性,以下这个是MyAnno的name属性
看着像一个方法,但实际上我们称之为属性name
如果一个注解中有属性,那么必须给属性赋值

public @interface MyAnno {
     public String show();
     int age() default 18;
}

public class MyAnnotationTest {
	//注解里age可以不写了,因为有默认值
	@MyAnno(name="aaa")
	public void doSome() {
	}
}
要求
1、属性的返回值类型有下列取值:基本数据类型,String,枚举,注解,以上类型的数组(不能是Integer,Double )
2、定义了属性,在使用时需要给属性赋值
	1、如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值
	2、如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
	3、数组赋值时,值使用{}包裹,如果数组中只有一个值,则{}可以省略

元注解

用于描述注解的注解

@Target:描述注解能够作用的位置
		@Target(ElementType.TYPE):可以作用在类上
		@Target(ElementType.METHOD):可以作用在方法上
		@Target(ElementType.FIELD):可以作用在成员变量上
@Retention:描述注解被保留的阶段
	@Retention(RetentionPolicy.CLASS):当前被描述的注解会保留到class字节码文件中,但不被JVM读到
	@Retention(RetentionPolicy.RUNTIME):当前被描述的注解会保留到class字节码文件中,并被JVM读到(被反射机制读取)
	@Retention(RetentionPolicy.SOURCE):只会保存在java源文件中,不会出现在class文件里,因为只给编译器看,所以编译后就没有用了
@Documented:描述注解是否被抽取到api文档中
@Inherited:描述注解是否被子类继承

解析(使用)注解

获取注解中定义的属性值
1、获取注解定义的位置的对象(Class,Method,Field)
2、获取指定的注解

getAnnotation(Class)
//其实就是在内存中生成了一个该注解接口的子类实现对象
/*
      public class ProImpl implements Pro {
          public String className() {
              return "annotation.Demo1";
          }
          public String methodName() {
              return "show";
          }
      }
 */

3、调用注解中的抽象方法获取配置的属性值

package annotation;

public class Demo1  {
    public void show() {
        System.out.println("Demo1...show...");
    }
}
package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 描述需要执行的类名和方法名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
    String className();
    String methodName();
}
package annotation;

import java.lang.reflect.Method;

@Pro(className = "annotation.Demo1",methodName = "show")
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //不改变该类的任何代码,可以任意类的对象,可以执行任意方法
        //1、解析注解
        //1。1、获取该类的字节码对象
        Class<ReflectTest> reflectTestClass = ReflectTest.class;
        //2、获取上边的注释对象
        //其实就是在内存中生成了一个该注解接口的子类实现对象
        /*
            public class ProImpl implements Pro {
                public String className() {
                    return "annotation.Demo1";
                }
                public String methodName() {
                    return "show";
                }
            }
         */
        Pro an = reflectTestClass.getAnnotation(Pro.class);
        //3、调用注解对象中定义的重新方法,获取返回值
        String className = an.className();
        String methodName = an.methodName();

        //4、加载对象进内存
        Class cls = Class.forName(className);
        Object obj = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(obj);
    }
}

在这里插入图片描述

反射注解

package annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "abc";
}

package annotation;

@MyAnnotation()
public class MyAnnotationTest {
}

package annotation;

public class ReflectAnnotationTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c = Class.forName("annotation.MyAnnotationTest");
        System.out.println(c.isAnnotationPresent(MyAnnotation.class));
        Class stringClass = Class.forName("java.lang.String");
        System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class));

        if(c.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
            System.out.println("类上面的注解对象");
            //获取对象上的属性
            String value = myAnnotation.value();
            System.out.println(value);
        }
    }
}

在这里插入图片描述

案例

package annotation.demo;

/**
 * 小明定义的计算器类
 */
public class Calculator {
    @Check
    public void add() {
        System.out.println("1+0="+(1+0));
    }
    @Check
    public void sub() {
        System.out.println("1-0="+(1-0));
    }
    @Check
    public void mul() {
        System.out.println("1*0="+(1*0));
    }
    @Check
    public void div() {
        System.out.println("1/0="+(1/ 0));
    }
    public void show() {
        System.out.println("永无bug...");
    }
}
package annotation.demo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
package annotation.demo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * 简单的测试框架
 * 当主方法执行后,会自动检测加了 @Check 的方法,判断方法是否有异常,记录到文件中
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1.创建计算器对象
        Calculator c = new Calculator();
        //2.获取字节码文件对象
        Class cls = c.getClass();
        //3.获取所有方法
        Method[] methods = cls.getMethods();
        int num = 0;//异常出现的次数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
        for (Method method : methods) {
            //4.判断方法上是否有Check注释
            if(method.isAnnotationPresent(Check.class)) {
                //5.执行
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    //6.捕获异常
                    num++;
                    bw.write(method.getName()+"方法出异常了");
                    bw.newLine();
                    bw.write("异常的名称 :"+e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("------------------------");
                    bw.newLine();
                }
            }
        }
        bw.write("本次测试一共出现"+num+"次异常");
        bw.flush();
        bw.close();
    }
}

在这里插入图片描述

注解在开发中有什么用?

需求:假设有这样一个注解,叫做;@id
这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类必须 有一个int类型 id属性。如果没有这个属性就报异常。如果有这个属性就正常执行

package annotation.annotation1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}


package annotation.annotation1;

@Id
public class User {
    int id;
    String name;
    String password;
}


package annotation.annotation1;

public class HasNotIdPropertyException extends RuntimeException{
    public HasNotIdPropertyException() {
    }

    public HasNotIdPropertyException(String s) {
        super(s);
    }
}


package annotation.annotation1;

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("annotation.annotation1.User");
        boolean isRigth = false;

        if(c.isAnnotationPresent(Id.class)) {
            Field[] fields = c.getDeclaredFields();
            for(Field field:fields) {
                if("id".equals(field.getName())&&"int".equals(field.getType().getSimpleName())){
                    isRigth = true;
                    break;
                }
            }
            if(!isRigth) {
                throw new HasNotIdPropertyException("被@id注解标注的类中必须要有int类型的id属性");
            }
        }
    }
}

小结

1、以后大多数时候,我们会使用注解,而不是自定义注解
2、注解给谁用?编译器和解析程序用
3、注解不是程序的一部分,可以理解为注解就是一个标签

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿炳的旅程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值