注解

注解

注解(Annotation)
也叫元数据,一种代码级别的说明,它是]DK1.5及以后版本引入的一个特性它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明。

注解和注释:
注解:用来说明程序,给计算机(虚拟机)看的
注释:用来对程序进行说明的文字,给程序员看的

Java中的常见注解:
@Override
用于指定方法是重写父类的方法,只能修饰方法,不能修饰其他程序元素。
@Override的作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法。

@Deprecated
用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告
Java 9为@Deprecated增加了两个属性:
since:该String类型的属性指定该API从哪个版本被标记为过时;
forRemoval:该boolean类型的属性指定该API在将来是否会被删除

@SuppressWarnings
指示被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告(抑制警告,阻止编译器显示警告信息)。
使用注解来关闭编译器警告时,一定要在括号里使用name =value 的形式为该注解的成员变量设置值。
(取消编译器的检查)
@SuppressWarnings(value =”all”)

[@SuppressWarnings注解的存在意义是告诉编译器忽略特定的警告信息,这样可以在特定情况下避免编译器产生警告,例如在一些特定的情况下,我们知道某些代码是安全的,但编译器可能会产生警告,这时可以使用@SuppressWarnings注解来告诉编译器忽略这些警告。这样可以提高代码的可读性和可维护性。然而,需要谨慎使用@SuppressWarnings注解,因为它可以隐藏潜在的问题,应该尽量避免使用。]

@Functionallnterface
Java 8新增的,只能用来修饰接口,表示该接口是一个函数式接口;
函数式接口:接口中有且仅有一个抽象方法;
Lambda表达式的使用前提: 接口中有且仅有一个抽象方法。

元注解

对注解进行注解的注解。也就是写在注解上面的注解。

两个常用元注解
@Retention 保留
@Target 目标

@Retention
只能用于修饰注解定义,用于指定被修饰的注解可以保留多长时间。
包含了一个RetentionPolicy类型的value成员变量,所以使用的@Retention时必须为该value成员变量指定。

@Retention中可使用的值定义在RetentionPolicy中,常用值如下:
RetentionPolicy.CLASS: 编译器把注解纪录在class文件中,当运行Java程序时,JVM不可获取注解信息,这是默认值
RetentionPolicy.RUNTIME: 编译器把注解纪录在lass文件中,当运行Java程序时,JVM也可获取注解信息,开发中常用
RetentionPolicy.SOURCE:注解只保留在源代码中,编译器直接丢弃这种注解

@Target
只能用于修饰注解定义,用于指定被修饰的注解能用于修饰哪些程序单元,包含一个名为value的成员变量

@Target中可使用的值定义在ElementType中,常用值如下
@Target(ElementType.TYPE): 可以用于接口、类、枚举、注解
@Target(ElementType.FIELD): 可以用于属性字段、枚举的常量
@Target(ElementType.METHOD): 可以用于方法
@Target(ElementType.PARAMETER): 可以用于方法参数
@Target(ElementType.CONSTRUCTOR): 可以用于构造函数
@Target(ElementType.LOCAL_VARIABLE):可以用于局部变量

自定义注解

定义格式:

1
2
3
4
//元注解
public @interface name{
//属性列表;
}

注解的本质:
public interface MyAnnotation extends Annotation{}
是一个接口,该接口默认继承Annotation接口
既然是接口,那么内部定义的内容,就是接口中可以定义的内容

属性:接口中的抽象方法
格式:返回值类型 属性名称()[default 默认值]

注解属性类型可以有以下列出的类型:
基本数据类型
String
枚举类型
注解类型
Class类型
以上类型的一维数组类型

注解的使用和解析

使用注解

如果注解有多个属性,则可以在注解括号中用“,”号隔开分别给对应的属性赋值。
如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
数组赋值时,值使用{}包裹。如果数组中只有一个值,则什可以省略。

解析注解

1
2
3
4
5
6
7
//获取字节码文件对象,获取谁的呢?谁使用了注解,就获取谁的
Class<MyAnnotationTest> c= MyAnnotationTest.class;
//获取字节码对象上的注解信息
MyAnnotation annotation =c.getAnnotation(MyAnnotation.class);
//解析注解
String name = annotation.name();
int age = annotation.age();

框架运行原理(通过注解运行指定类中的指定方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation{
String className();
String methodName();
}

//使用类
@MyAnnotation(className = "com.itheima_05.Student",methodName = "study")
public class MyAnnotation{
public static void main(String[] args) {
//获取字节码对象
Class<MyAnnotationTest> cc = MyAnnotationTest.class;
//通过字节码文件对象获取注解对象
MyAnnotation myAnnotation = cc.getAnnotation(MyAnnotation.class);

//通过注解对象的属性获取值
String className = myAnnotation.className();
String methodName = myAnnotation.methodName();


//反射操作
//通过类名反射得到Class对象
Class<?> c = Class.forName(className);
//通过Class对象创建一个对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//通过Class得到方法对象
Method m = c.getMethod(methodName);
//调用方法
m.invoke(obj);
}
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信