注解的定义
Annotation JDK 1.5 开始引入的新技术,对 package,class,method,field 做出一些注释,并且,可以被程序或者 IDE 读取写入。
内置注解
@Override (重写)
@Deprecated (废弃) => 被标注则意味着废弃的注解现在被废弃了 (啊哈哈哈哈)
@SafeVarargs (忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告)
@FunctionallInterface (函数式接口) | 编程格式检查
@Repeatable (标识某注解可以在同一个声明上使用多次)
@SuppressWarnings (抑制编译时的警告信息) => 变灰暗的类啥的标识这个注解后会不提示警告
元注解
@Target - 标记这个注解应该是哪种 Java 成员
package java.lang.annotation;
public enum ElementType {
TYPE, /* 类、接口(包括注释类型)或枚举声明*/
FIELD, /* 字段声明(包括枚举常量)*/
METHOD, /* 方法声明*/
PARAMETER, /* 参数声明*/
CONSTRUCTOR, /* 构造方法声明*/
LOCAL_VARIABLE, /* 局部变量声明*/
ANNOTATION_TYPE, /* 注释类型声明*/
PACKAGE /* 包声明*/
}
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问
package java.lang.annotation;
public enum RetentionPolicy {
/* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了*/
SOURCE,
/* 编译器将Annotation存储于类对应的.class文件中。默认行为*/
CLASS,
/* 编译器将Annotation存储于class文件中,并且可由JVM读入*/
RUNTIME
}
@Documented - 标记这些注解是否包含在用户文档 javadoc中
@Inherited - 标记这个注解是自动继承的
自定义注解实例
自定义注解一般都会配合反射使用,利用反射获取到标注的方法,变量或者是类,然后对其进行处理
@Documented //可以写在文档里
@Target(ElementType.TYPE) //这个注解在类上描述
@Retention(RetentionPolicy.RUNTIME) //作用域策略, 存储于class中, JVM读入
@Inherited //允许继承
public @interface MyAnnotation {
String annotationTest() default “Test”;
}
@MyAnnotation("new Test")
public class AnnotationTest {
public static void main() {
// ....
}
}
java的内存模型
程序运行---》类加载器 ----》将数据加载进入方法区,并在堆上生成对应的.class文件 ----》执行栈上的 mian 方法----》初始化变量信息
注:对象的实例化是在堆上进行的,静态变量与常量均是存于方法区中。

image.png
反射
反射是一种通过对象,或者类路径获取到 class的一种技术,它很重要 !!! 反射的效率相对来说,是比较耗时的,在使用的反射的时候,可以通过下面的方法,提高效率:
setAccessible(boolean flag)
如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的方法)
1.获取class的几种方式
com.java.demo.Book.class 或 Book.class
Class book.getClass();
Class.forName("com.java.demo.Book");
注:前两种方式需要Book类存在,第三种方式是动态编程的方式进行加载, 不需要先建立类
2.获取Constructor
通过指定的参数类型, 获取指定的单个构造方法
getConstructor(参数类型的class对象数组)
例如:
构造方法如下: Person(String name,int age)
得到这个构造方法的代码如下:
Constructor c = p.getClass().getConstructor(String.class,int.class);
获取构造方法数组
getConstructors();
获取所有权限的单个构造方法
getDeclaredConstructor(参数类型的class对象数组)
获取所有权限的构造方法数组
getDeclaredConstructors();
3. 获取Method
getMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(public修饰的)
getMethods();
得到一个类的所有方法 (public修饰的)
getDeclaredMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认)
getDeclaredMethods();
得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认)
4. 执行对应的方法
//加载类
Class c1 = Class.forName(包名+类名);
//获取构造方法
Constructor c = c1.getConstructor();
//创建对象
Object o = c.newInstance();
//获取类中的指定参数的方法
Method setName = c1.getMethod("setName", String.class);
//忽略权限的获取类中的方法
Method setAge = c1.getDeclaredMethod("setAge", int.class);
setAge.setAccessible(true);
//调用setName()方法
setName.invoke(o, "参数")
5. 获取Field
//加载类
Class clazz= Class.forName(包名+类名);
clazz.getDeclaredField(String filedName)
根据属性的名称, 获取一个属性对象 (所有属性)
clazz.getDeclaredFields()
获取所有属性
clazz.getField(String filedName)
根据属性的名称, 获取一个属性对象 (public属性)
clazz.getFields()
获取所有属性 (public)
实例:
//加载类
Class c = Class.forName(包名+类名);
//获取构造器
Constructor ct = c.getConstrutor();
//创建对象
Object o = ct.newInstance();
//获取属性值
Field name = c.getField("name");
name.set(o, "阿乐");
//忽略权限的获取属性值
Filed age = c.getDeclaredField("age");
name.setAccessible(true);
name.set(o, 21);
6.反射获取注解信息!!!
直接上代码
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {
String name() default "mao";
int age() default 18;
}
@MyTestAnnotation(name = "father",age = 50)
public class Father {
}
/**是否存在对应 Annotation 对象*/
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
/**获取 Annotation 对象*/
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
/**获取所有 Annotation 对象数组*/
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
public class test {
public static void main(String[] args) throws NoSuchMethodException {
/**
* 获取类注解属性
*/
Class<Father> fatherClass = Father.class;
boolean annotationPresent = fatherClass.isAnnotationPresent(MyTestAnnotation.class);
if(annotationPresent){
MyTestAnnotation annotation = fatherClass.getAnnotation(MyTestAnnotation.class);
System.out.println(annotation.name());
System.out.println(annotation.age());
}
/**
* 获取方法注解属性
*/
try {
Field age = fatherClass.getDeclaredField("age");
boolean annotationPresent1 = age.isAnnotationPresent(Age.class);
if(annotationPresent1){
Age annotation = age.getAnnotation(Age.class);
System.out.println(annotation.value());
}
Method play = PlayGame.class.getDeclaredMethod("play");
if (play!=null){
People annotation2 = play.getAnnotation(People.class);
Game[] value = annotation2.value();
for (Game game : value) {
System.out.println(game.value());
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}

image.png