Java 注解和反射
P1: 注解
- 内置注解:Override
- 元注解(负责注解其他注解):1. @Target 描述注解的使用范围
2. @Retention 用于描述注解的生命周期,一般是RUNTIME
2. @Document
2. @Inherited - 自定义注解:
P6: 反射
反射是 Java 被视为动态语言的关键。
Class c = Class.forName("java.lang.String")
加载完类后,在堆内存的方法区就产生了一个 Class 类型的对象(一个类只有一个 Class 对象),这个对象包含了完整的类结构信息。
P7: 得到 Class 类的几种方式
Person person = new Student(); //父类的引用指向子类的对象
//方式一:
Class c1 = person.getClass(); //Student类
//方式二:
Class c2 = Class.forName("com.kuang.reflection.Student"); //通过包名
//方式三:
Class c3 = Student.class;
/*
*一个类只有一个 Class 对象, c1, c2, c3 的 hashcode 值相同。
*/
P9: 类的加载内存分析
-
加载:将 class 文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的 java.lang.Class 对象。
-
链接:将 java类的二进制代码合并到 JVM 的运行状态之中的过程。
- 验证:确保加载的类信息符合 JVM 规范,美誉哦安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
-
初始化:
- 执行类构造器 () 方法的过程。类构造器 () 方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。
- 当初始化一个类时,如果其父类还没有进行初始化,则需要首先初始化父类。
- 虚拟机会保证一个类的 () 方法在多线程环境中被正确枷锁和同步。
1. 加载到内存,产生一个类对应 Class 对象
2. 链接,链接结束后 m=0
3. 初始化
<clinit>{
System.out.println("A类静态代码块初始化");
m = 300;
m = 100;
}
P10: 类的初始化
- Main 类首先被加载
- 父类加载
- 子类加载
- 运行 main 函数
P13: 动态创建对象
// 获得Class对象
Class c1 = Class.getName("com.kuang.reflection.User");
//1. 构造一个对象
User user = (User)c1.newInstance(); // 实际上是调用无参构造器
//2. 通过调用构造器
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class,int.class);
User user2 = (User)constructor.newInstance("xiaoming", 001,18);
//3. 通过反射调用普通方法
User user3 = (User)c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3, "xiaoming");
//4. 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 私有属性,关闭安全检测
name.setAccessible(true);
name.set(user4, "xiaoming");