反射原理分析
1、反射
1.1、反射原理
1、类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
□ 加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象
□ 连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
□ 初始化
类的加载
2、 类加载器
□ 负责将.class文件加载到内在中,并为之生成对应的Class对象。
□ 虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行
3、类加载器的组成
□ Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
□ Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
□ System ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
2.1、公共类
A接口
public interface A {
}
B接口
public interface B {
}
User类
public class User implements A,B{
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
}
2.1、三种方式获取类的字节码文件的对象
//三种方式获得 类的字节码文件 的对象
//1、方式 通过类.class来获取 类的字节码文件 的对象
Class clazz = User.class;
System.out.println(clazz);
//2、方式 通过对象.getClass()来获取 类的字节码文件 的对象
User user = new User();
Class class1 = user.getClass();
System.out.println(class1);
//3、通过Class.froName()来获取 类的字节码文件 的对象
Class class2 = Class.forName("com.itheima.reflect.User");
System.out.println(class2);
System.out.println(class1==class2);//true
System.out.println(clazz==class2);//true
2.2、获取构造器并创建对象。
//通过Class.froName()来获取 类的字节码文件 的对象
Class clazz = Class.forName("com.itheima.reflect.User");
//无参数的
//通过class对象获取类的构造器。
Constructor constructor = clazz.getConstructor();
//通过构造器创建对象
User user = (User)constructor.newInstance();
System.out.println(user);
//有参数的
//通过class对象获取类的构造器。
Constructor c2 = clazz.getConstructor(String.class,String.class);
//通过构造器创建对象
User user2 = (User)c2.newInstance("zhangsan","123");
System.out.println(user2);
2.3、获取方法并执行
//通过Class.froName()来获取 类的字节码文件 的对象
Class clazz = Class.forName("com.itheima.reflect.User");
//通过clazz对象创建一个User的对象
User user = (User)clazz.newInstance();
//获取有参数的方法并执行
//通过getMethod获取clazz对象里面的方法
Method method = clazz.getMethod("setUsername", String.class);
method.invoke(user, "lisi");
//获取无参数的方法并执行
Method method1 = clazz.getMethod("getUsername");
String name = (String)method1.invoke(user);
System.out.println(user);
System.out.println(name);
2.4、获得类的所有的接口
//三种方式获得 类的字节码文件 的对象
//1、方式 通过类.class来获取 类的字节码文件 的对象
Class clazz = User.class;
Class[] interfaces = clazz.getInterfaces();
for (Class class1 : interfaces) {
System.out.println(class1);
}