注解
- 定义: 注解是可以在源码层次上进行操作,或者可以处理编译器在其中放置了注解的类文件
- java对有无注解的代码会生成相同的虚拟机指令,但是添加注释可以有利于我们后期开发与使用
- 注解使用时以** @ **开头
public class test01 {
public static final Logger LOGGER = LoggerFactory.getLogger(test01.class);
//@Test 这个注解是使一个方法变成一个测试方法,使得可以独立运行,同时需要注意这个注解需要在适当工具的辅助下才可以使有
@Test
public void test() throws Exception {
LOGGER.error("error");
LOGGER.warn("warn");
LOGGER.info("info");
LOGGER.debug("debug");
LOGGER.trace("trace");
}
}
// @SuppressWarnings("") 在类的上方是压制整个类的警告,在方法上时压制方法的警告
// 如果你使用 IDEA 你会发现当你吧这条语句注释后,a会发出警告
public class Test1 {
@SuppressWarnings("看注释")
public static void main(String[] args) {
int a;
}
}
//@Override 这个注解的意思是覆盖父类的方法,同时也起到了一定的检查作用
public class Test1 {
@Override
public String toString() {
return "Test1{}";
}
}
//@Deprecated 这个注解的意思是该方法已废除,但是该方法仍然可以使用
public class Test1 {
public static void main(String[] args) {
f();
}
@Deprecated
public static void f()
{
}
}
注释:
SuppressWarnings(“链接”)
注解接口
//注解的生成方式
@interface 注解名{
类型名 名称(); //注解元素的类型:基本类型 String Class enum类型 注解类型
}
使用方法:
public class HelloWord {
@My(value = "",name = "")// 进行注解中的数据赋值 看下方
static <T> void f1(List<T> list)
{
T t = list.get(0);
System.out.println("f1");
System.out.println(t.getClass().getSimpleName());
}
}
//元注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface My{
String value() default ""; // default 生成一个默认值,
// 需要注意的是 默认值并不是和注解存储在一起而是动态计算的,当我们重新修改了默认值后,重新编译此注解,则所有使用该注解的默认值都会发生修改
String name() default "";
}
注解中的元素赋值:
赋值时的顺序无所谓,赋值格式: “”名字 = 数据”;
当我们的注解中只有一个元素时,将该注解的名称设为: value(); 这样在使用该注解对其中的数据赋值时,可以不用写名称,只有在注解中只有一个数据时并且数据声明为value才可以省略,否则会报错
其他的一些注解
@NonNull 在使用的时候,放在变量前面,告诉编译器该变量的类型不为空
@ReadOnly 使用在方法的参数,标明该参数在方法中不会修改
元注解
元注解是用来注解其他注解的,java定义四个meta-annotation,他们被用来提供对其他的annation类型做说明,这些类可以在java.lang.annation包中可以找到{@Target, @Retention, @Documented, @inherited }
@Target 被用来描述注解的使用范围(即可以使用在什么地方 )
@Retention 表示需要在什么级别保存信息,描述注解的生命周期 级别大小为:(SOURCE < CLASS < RUNTIME)一般选择最后一个
@Documented 说明注解被包含在 javadoc 中
@Inherited 说明子类可以继承父类的该注解
//括号内的值 进行源码追踪就可以知道
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnation{
String name();
int id();
int n();
}
容器注解
在JavaSE8,以后,将同种注解多次应用于某一项是合法的,对于重复注解的实现这来说需要提供一个容器注解,它可以将这些注解存储到一个数组中
public class HelloWord {
@Test_Classe(
{ @Test_Class(name = "1次", exacpet = "1次"),
@Test_Class(name = "2次", exacpet = "2次"),
@Test_Class(name = "3次", exacpet = "3次")}
)
public static void f( Integer a)
{
a = 20;
}
}
/**
* @author Lenovo
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test_Class{
String name();
String exacpet();
}
/**
* 容器
* @author Lenovo
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test_Classe {
Test_Class[] value();
}
使用反射获取注解
package com.company;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author Lenovo
* @version 1.0
* @Date 2021/9/18 21:13
*/
@Mysql(value = "mysql",name = "hello")
public class Student extends A{
@Mysql_student(row_name = "name", Type = "VarChar",row = 1)
private String name;
@Mysql_student(row_name = "id", Type = "long",row = 2)
private long id;
@Mysql_student(row_name = "Grade", Type = "int",row = 3)
private int Grade;
public Student(String name, long id, int grade) {
this.name = name;
this.id = id;
Grade = grade;
}
@Test_Classe({
@Test_Class(name = "1ci", exacpet = "1ci"),
@Test_Class(name = "1ci", exacpet = "1ci"),
@Test_Class(name = "3ci", exacpet = "3ci")}
)
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id=" + id +
", Grade=" + Grade +
'}';
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
final Class<?> c1 = Class.forName("com.company.Student");
// getAnnotations 获取作用域该项的所有注解包括继承来的注解
// @com.company.parent(10)
//@com.company.Mysql(value="mysql", name="hello")
var annotations = c1.getAnnotations();
for (int i = 0; i < annotations.length; i++) {
System.out.println(annotations[i]);
}
// getAnnotations 获取作用域该项的所有注解不包括继承来的注解
// @com.company.Mysql(value="mysql", name="hello")
var declaredAnnotations = c1.getDeclaredAnnotations();
System.out.println(Arrays.toString(declaredAnnotations));
//getAnnotation 获得给定类型的注解
//mysql
//hello
var annotation = c1.getAnnotation(Mysql.class);
System.out.println(annotation.value());
System.out.println(annotation.name());
// 获得类指定的注解 -- 域
//[@com.company.Mysql_student(row_name="name", Type="VarChar", row=1)]
//name
//1
//VarChar
Field name = c1.getDeclaredField("name");
var annotations1 = name.getAnnotations();
System.out.println(Arrays.toString(annotations1));
var annotation1 = name.getAnnotation(Mysql_student.class);
System.out.println(annotation1.row_name());
System.out.println(annotation1.row());
System.out.println(annotation1.Type());
//判断给定项是否有该注解
//true
//true
//true
//false
System.out.println(c1.isAnnotationPresent(Mysql.class));
System.out.println(c1.isAnnotationPresent(parent.class));
System.out.println(name.isAnnotationPresent(Mysql_student.class));
System.out.println(name.isAnnotationPresent(parent.class));
获得类指定的注解 -- 方法
//[@com.company.Test_Classe({@com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="3ci", exacpet="3ci")})]
Method toString1 = c1.getDeclaredMethod("toString");
var annotations2 = toString1.getAnnotations();
System.out.println(Arrays.toString(annotations2));
//使用容器时需要注意使用getAnnotationsByType 返回一个数组
//[@com.company.Test_Classe({@com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="3ci", exacpet="3ci")})]
var annotation3 = toString1.getAnnotationsByType(Test_Classe.class);
System.out.println(Arrays.toString(annotation3));
//@com.company.Test_Classe({@com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="1ci", exacpet="1ci"),
// @com.company.Test_Class(name="3ci", exacpet="3ci")})
Annotation annotation6 = toString1.getAnnotation(Test_Classe.class);
System.out.println(annotation6);
//null
Annotation annotation5 = toString1.getAnnotation(Test_Class.class);
System.out.println(annotation5);
}
}
@parent(10)
class A { }
/**
* @author Lenovo
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface parent {
int value();
}
/**
* @author Lenovo
*/
@Target(ElementType.TYPE) // 描述注解使用范围
@Retention(RetentionPolicy.RUNTIME) // 描述注解的生命周期
@Documented()// 该注解将被包含在javadoc中
@Inherited // 子类可以继承父类的该注解
@interface Mysql {
String value();
String name();
}
/**
* @author Lenovo
*/
@Target(ElementType.FIELD) // 描述注解使用范围
@Retention(RetentionPolicy.RUNTIME) // 描述注解的生命周期
@Documented()// 该注解将被包含在javadoc中
@Inherited // 子类可以继承父类的该注解
@interface Mysql_student {
String row_name();
String Type();
int row();
}
/**
* @author Lenovo
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test_Class{
String name();
String exacpet();
}
/**
* 容器
* @author Lenovo
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test_Classe {
Test_Class[] value();
}