java反射更改⽅法内容_Java反射
类的加载
java运⾏的都是类
当程序要使⽤某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现这个类进⾏初始化。
加载
加载,是指Java虚拟机查字节流(查.class⽂件),并且根据字节流创建java.lang.Class对象的过程。这个过程,将类的.class⽂件中的⼆进制数据读⼊内存,放在运⾏时区域的⽅法区内。然后在堆中创建java.lang.Class对象,⽤来封装类在⽅法区的数据结构。
类加载阶段:
(1)Java虚拟机将.class⽂件读⼊内存,并为之创建⼀个Class对象。
(2)任何类被使⽤时系统都会为其创建⼀个且仅有⼀个Class对象。
(3)这个Class对象描述了这个类创建出来的对象的所有信息,⽐如有哪些构造⽅法,都有哪些成员⽅法,都有哪些成员变量等。
连接
链接包括验证、准备以及解析三个阶段。
验证阶段:主要的⽬的是确保被加载的类(.class⽂件的字节流)满⾜Java虚拟机规范,不会造成安全错误。
准备阶段:负责为类的静态成员分配内存,并设置默认初始值。
解析阶段:将类的⼆进制数据中的符号引⽤替换为直接引⽤。
说明:
符号引⽤。即⼀个字符串,但是这个字符串给出了⼀些能够唯⼀性识别⼀个⽅法,⼀个变量,⼀个类的相关信息。
直接引⽤。可以理解为⼀个内存地址,或者⼀个偏移量。⽐如类⽅法,类变量的直接引⽤是指向⽅法区
的指针;⽽实例⽅法,实例变量的直接引⽤则是从实例的头指针开始算起到这个实例变量位置的偏移量。
举个例⼦来说,现在调⽤⽅法hello(),这个⽅法的地址是0xaabbccdd,那么hello就是符号引⽤,0xaabbccdd就是直接引⽤。
在解析阶段,虚拟机会把所有的类名,⽅法名,字段名这些符号引⽤替换为具体的内存地址或偏移量,也就是直接引⽤。
初始化
初始化,则是为标记为常量值的字段赋值的过程。换句话说,只对static修饰的变量或语句块进⾏初始化。
如果初始化⼀个类的时候,其⽗类尚未初始化,则优先初始化其⽗类。
如果同时包含多个静态变量和静态代码块,则按照⾃上⽽下的顺序依次执⾏。
类的初始化时机
1.创建类的实例
2.使⽤类的静态变量,或者为静态变量赋值
3.调⽤类的静态⽅法
4.使⽤反射强制创建某个类或接⼝对应的java.lang.Class对象
5.初始化某个类的⼦类
6.直接运⾏某个类
类的加载器
BootStrapLoader(根类加载器)
⽤来加载java的核⼼类,⽐如System,String等。这些类在jre的lib⽬录下rt.jar中
ExtClassLoader(扩展类加载器)
负责jre的扩展⽬录中的jar包加载,这些类在jre的lib⽬录下的ext中
AppClassLoader(系统类加载器)
负责在JVM启动时加载来⾃Java命令的class⽂件,以及classpath环境变量所制定的jar包和类路径。
加载程序员⾃⼰写的类
反射
JAVA反射机制是在运⾏状态中,对于任意⼀个类,都能够知道这个类的所有属性和⽅法;对于任意⼀个对象,都能够调⽤它的任意⽅法和属性;这种动态获取信息以及动态调⽤对象⽅法的功能称为java语⾔的反射机制。
获取字节码⽂件对象(Class)的三种⽅式
1.Object中的getClass⽅法来获取Class对象
Object obj=new Proson();
Class clazz1 =Class();
2.直接通过 类名.class来获取Class对象
Class clazz2=Proson.class;
3.通过Class 对象的forName()静态⽅法来获取Class对象
Class clazz3 = Class.forName("com.xiaoli.bean.Proson");
⼀个类在 JVM 中只会有⼀个 Class 实例
泛型擦除
编译后产⽣的.class⽂件没有泛型约束,这种现象称为泛型擦除
反射展⽰泛型擦除效果
ArrayList arr = new ArrayList();
arr.add("a");
//反射获取ArrayList类的class⽂件对象
Class c = Class();
Method method = c.getMethod("add",object.class);
/
/实现向String类型的ArrayList中加⼊整型
method.invock(array,1)
通过配置⽂件更改运⾏内容
public class Person {
public void eat(){
System.out.println("⼈在吃饭");
}
}
public class Student {
public void study(){
System.out.println("学⽣在学习");
}
}
public class Worker {
public void job(){
System.out.println("上班族在⼯作");
}
}
public class Test {
public static void main(String[] args) throws Exception{ //IO流读取配置⽂件
FileReader r = new FileReader("config.properties");
//创建集合对象
Properties pro = new Properties();
//调⽤集合⽅法load,传递流对象
pro.load(r);
java设置环境变量的方法代码r.close();
//通过键获取值
String className = Property("className"); String methodName = Property("methodName"); //反射获取指定类的class⽂件对象
Class c = Class.forName(className);
Object obj = c.newInstance();
//获取指定的⽅法名
Method method = c.getMethod(methodName); method.invoke(obj);
}
}
配置⽂件:
className=cn.itcast.demo3.Student
methodName=study
className=cn.itcast.demo3.Person methodName=eat
className=cn.itcast.demo3.Worker methodName=job
使⽤时注释掉不需要的即可