反射_Java.Reflection
动态语言
运行时可以改变结构的语言,运行时代码可以根据某些条件改变自身结构。JS、PHP..
静态语言
运行时结构不可变的语言。Java、C、C++
Reflection反射
-
反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。
-
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这和对象看到类的结构。
-
正常方式:引入需要的包,类名称----->new实例化------>取得实例化对象
-
反射方式:实例化对象------>getClass()方法------>得到完整的包,类名称
-
优点:实现动态创建和编译,灵活性提高。
-
缺点:对性能有影响。
通过反射获得对象的方式
- 通过对象获得
Person p = new Student();
Class c = p.getClass();
- forname获得
Class c = Class.forName("com.sx.thread.Student");
- 通过类名.class获得
Class c = Student.class;
- 基本内置对象的包装类都有一个TYPE属性
Class type = Integer.TYPE;
- 通过反射的对象c还可以获取父类等对象
Class c1 = c.getSuperclass();
从内存分析反射
java内存分为:
- 堆:存放new出来的对象
- 栈:存放基本类型、引用对象类型的变量
- 方法区:包含所有class和static变量
-
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换为方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。(class是加载到内存中才有的,所以只能人为获取,不能主动创建)
-
链接:将Java类的二进制代码合并到JVM运行时状态之中的过程
- 验证:确保代码没有问题。
- 准备:为类变量(static)分配内存并设置变量的默认初始值。
- 解析:虚拟机常量池内的符号引用(常量名)替换为是直接引用(地址)的过程。
-
初始化:
- 执行类构造器
()方法的过程。构造器类 ()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。 - 当初始化一个类的时候,如果发现父类还没有初始化,则需要先触发其父类的初始化。
- 虚拟机会保证一个类的
()方法在多线程环境中被正确加锁和同步。
- 执行类构造器
package com.sx.thread;
public class Test02 {
public static void main(String[] args) {
A a = new A();
System.out.println(a.m);
}
}
class A{
static {
System.out.println("A类静态代码块初始化");
m=300;
}
static int m = 100;
public A() {
System.out.println("A类的无参构造初始化");
}
}
输出:
A类静态代码块初始化
A类的无参构造
100
上述代码执行过程:
- 加载到内存,产生一个类对应的class对象
- 链接,链接结束后产生m的默认值0
- 初始化执行
(){}方法将静态内容合并到一起(按顺序)这里先执行了m=300;又执行了m=100;