反射
反射机制
反射快速入门
利用反射机制加载配置文件实现对象实例化,并调用方法
package com.czl.re;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @author CaoZiLiang
* @date 2022/9/8 11:53
*/
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/re.properties"));
String classfullpath = properties.getProperty("classfullpath");
String method1 = properties.getProperty("method");
//利用反射机制加载配置文件实现对象实例化,并调用方法
//(1) 加载类 , 返回Class 类型的对象cls
Class cls = Class.forName(classfullpath);
//(2)通过cls 得到加载的类的对象实例
Object o = cls.nwInstance();
System.out.println(o.getClass());//运行对象
//(3) 可以通过cls的到加载的类的方法名为(cry)的方法对象
//在反射中,可以把方法视为对象
Method cry = cls.getMethod(method1);
//(4)通过方法对象来调用方法
cry.invoke(o); //传统 对象.方法() 反射机制 方法.invoke(对象)
}
}
re.properties
classfullpath=com.czl.re.Cat
method=cry
package com.czl.re;
/**
* @author CaoZiLiang
* @date 2022/9/9 15:05
*/
public class Cat {
private String name = "招财猫";
public void cry(){
System.out.println("hi"+name);
}
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwfEe77h-1664163338072)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220909152249833.png)]
java程序在计算机三阶段
代码阶段/编译阶段 —》javac编译得到 .class 字节码文件
Class类阶段(加载阶段)
Runtime运行阶段
new 对象 ,进行类加载,通过类加载器在堆中开辟空间
通过反射得到类成员变量,无参构造器,有参构造器
//得到int字段
//getField 不能得到private属性
Field age = cls.getField("age");
System.out.println(age.get(o)); //传统 对象.成员变量 --》反射: 成员变量对象.get(对象)
//无参构造
Constructor constructor = cls.getConstructor();
System.out.println(constructor);
Constructor constructor1 = cls.getConstructor(String.class);
System.out.println(constructor1);
package com.czl.re;
/**
* @author CaoZiLiang
* @date 2022/9/9 15:05
*/
public class Cat {
private String name = "招财猫";
public int age = 10;
public Cat(){}
public Cat(String name){
this.name = name;
}
public void cry(){
System.out.println("hi"+name);
}
}
反射调用优化
Method Field Constructor 对象都有setAccessible()方法,启动和禁用访问安全检查的机关,参数为true,取消访问检查,加快效率
Class类
获取Class对象的六种方式
Class.forName(“”)// 多用于配置文件,读取类全路径
类.class //用于参数传递
对象.getClass() // 运行类型 (复习多态)
类加载器 ClassLoader.getClassLoader
类加载
定义:将编译后的字节码文件,通过类加载器,加载到堆,并且生成一个Class对象,并且在方法区生成字节码文件的二进制数据(元数据)
通过反射完成类加载
静态加载:编译时就会加载,如果没有就报错
动态加载:代码执行到才会进行加载,编译时不会加载
类加载时机
(1)new对象时 //静态
(2) 子类被加载,父类也被加载 //静态
(3)调用类中的静态成员时 //静态
(4 )通过反射 //动态
类加载流程
源码 ->编译-> 字节码文件 ->运行-> 类加载{ [加载Loading] >>> [连接linking(验证、准备、解析)] >>> [初始化initialization] }
类加载五个阶段分析
1 加载阶段
(1)JVM在该阶段的主要目的是将字节码从不同的数据源(class文件,jar包,或网络等等)转化为二进制字节流加载到内存中,并乘胜一个代表该类的Java.lang.Class对象
2 连接 -验证
(1)确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
(2)可以考虑使用**-Xverify:none** 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间
3 连接 -准备
(1)JVM会在该阶段对类变量,分配内存并默认初始化(是初始化,只分配内存,不赋值)
例子:
public int n= 10; //实例类型,不会分配内存
public static int n = 10; // 类变量 分配内存并初始化为 0 ,不是20
public static final int n = 10; // 常量 赋值就不变 n=10
4连接 -解析
(1)虚拟机将常量池内的符号引用替换为直接引用过程 即
5初始化
(1) 开始执行类中定义的java程序代码,执行()方法的过程
(2)() 编译器按语句在源文件中出现的顺序,一次自动收集类中的所有静态变量的赋值和静态代码块中的语句,并进行合并
(3) 虚拟机会保证一个类的()方法在多线程坏境中被正确的加锁,同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都去要阻塞等待,直到活动线程执行()方法完毕
()方法的过程
(2)() 编译器按语句在源文件中出现的顺序,一次自动收集类中的所有静态变量的赋值和静态代码块中的语句,并进行合并
(3) 虚拟机会保证一个类的()方法在多线程坏境中被正确的加锁,同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都去要阻塞等待,直到活动线程执行()方法完毕