Java 注解

Java 注解

注解的一般形式 :

public @interface 注解名{
    属性;
}

注解的本质

  1. 自定义一个注解

    public @interface MyAnno{}
    
  2. 通过 cmd 控制台 javac 自定义注解 生成 MyAnno.class 文件

  3. 通过 javap 反编译 MyAnno.class 得到:

    Compiled from "MyAnno.java"
    public interface MyAnno extends java.lang.annotation.Annotation {}
    
  4. 由此可知,注解 的本质就是 interface ,所有的 注解都继承 java.lang.annotation.Annotation 这个类

注解的属性

  • 注解中的抽象方法称为注解的属性

  • 属性的要求

    • 返回值必须为以下数据类型

      1. 基本的数据类型
        • byte short int long
        • float double
        • boolean
        • char
      2. String
      3. String []
      4. 枚举
      5. 注解
    • 定义的属性要对属性赋值

      1. 例如:自定义的一个注解,里面有两个属性

        public @interface MyAnno {
        	String name() default "张三"; //属性 可以使用default指定默认值,指定默认值后使用可以无需再指定
            int age();
        }
        
      2. 使用时:

        @MyAnno(age = 21,name = "李四")
        public class AnnoTest {}
        

        必须将所有未指定默认值的属性全部赋值,形式类似于 Key—Value (这也是将注解中抽象方法称为属性的原因)

元注解

  • 元注解就是描述注解的注解
  • 四大元注解:
    • @Target 描述注解可以作用的范围
      • 属性的取值
        1. TYPE 可以作用再某类上
        2. METHOD 可以作用在某方法上
        3. FILED 可以作用在属性上
    • @Retention 描述注解可以保留的阶段
      • 属性的取值
        1. SOURCE 保留到源文件阶段
        2. CLASS 保留到字节码阶段
        3. RUNTIME 保留到运行时阶段
    • @Documented 描述注解是否可以抽取到api文档上
    • @Inherited 描述注解是否被子类继承

注解使用实例

  • 要求:不改变一个类的代码,获取类的所有属性,获取类的所有方法
  1. 创建自定义注解
package cn.test.anno;

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 MyAnno {
	String className();
	String classMethod();
}

2.创建一个测试类

package cn.test.bean;

public class TestBean {
	public void show() {
		System.out.println("恭喜你获得到了show()方法");
	}
}

  1. 测试注解
package cn.test.anno;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@MyAnno(className = "cn.test.bean.TestBean", classMethod = "show")
public class TestAnno {
	public static void main(String[] args) throws Exception {
		// 获取本类字节码
		Class clazz = TestAnno.class;
		// 获取本类注释对象
		MyAnno an = (MyAnno) clazz.getAnnotation(MyAnno.class);
		// 获取注释值
		String className = an.className();
		String classMethod = an.classMethod();

		// 创建测试对象字节码
		Class<?> cl = Class.forName(className);
		// 获取测试对象
		/*
		 * (底层生产一个 impl 类 来实现 注解,并对注解类中方法进行重写) 例如
		 class MyAnnoImpl implements MyAnno {
				@Override
				public String className() {
					return "cn.test.bean.TestBean";  //返回传入的值
				}
			
				@Override
				public String classMethod() {		//返回传入的值
					return "show";
				}
			}
		 */
        //获取测试类对象
		Object obj = cl.getConstructor().newInstance();
		Method method = cl.getMethod(classMethod);
		method.invoke(obj);

	}
}


小结

在以后的学习中我们很少进行自定义注解,一般情况直接使用注解就行,所以注意用途:

  1. 一般给 编译器 用
  2. 一般给解析程序用
  3. 注解不是一个方法中的组成部分(方法没了注解仍然是方法)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值