类加载--
当程序需要使用某个类的时候,如果该类还未被加载到内存中,则系统会通过类的加载、类的连接、类的初始化
这三个步骤对类进行初始化,如果不出现意外,JVM将会连续完成这三个步骤,所有这三个步骤类加载或者类初始化。
类的加载:就是指将class文件读入内存,并为之创建一个java.lang.class对象;
类的连接:
验证阶段:用于检验被加载的类是否有正确的内部结构
准备阶段:负责为类的类变量分配内存,并设置默认初始化值
解析阶段:将类的二进制数据中的符号引用替换为直接引用
类的初始化:
这一阶段主要对类的变量进行初始化
初始化步骤:
如果类还未被加载和连接,则程序先加载并连接该类;
假如该类的直接父类还未被初始化,则先初始化其直接父类;
加入类中有初始化语句,则系统依次执行这些初始化语句;
类加载器:负责将 .class 文件加载到内存中,
ClassLoader: 负责加载类的对象
主要方法:
getSystemclassLoad() 返回用于委派的系统类加载器
getParent() 放回父类加载器用于委派
public class ClassLoadDemo {
public static void main(String[] args) {
//获得系统类加载器
ClassLoader c = ClassLoader.getSystemClassLoader();
// 获取父类加载器
ClassLoader p = c.getParent();
System.out.println(p);
}
}
反射:
对某个类:
1、反射获取class对象的方法由三种:
Class<Employee> c = Employee.class; //返回Employee类的class对象
Employee e = new Employee;
Class c2 = e.getclass();
Class cl = Class.forName("col.student.Student"); //括号里面的类必须是包含包名的全路径
2、反射获取构造方法并使用:
import col.student.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ClassLoadDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取类的class对象
Class c = Class.forName("col.student.Student");
//获取类中的构造方法
Constructor<?>[] cons = c.getConstructors(); // 只能获取公有public的构造方法
Constructor<?>[] cons1 = c.getDeclaredConstructors(); //返回所有构造方法的数组
Constructor<?> cons2 = c.getConstructor();//返回一个Constructor对象,该对象
//反映由该Class对象表示的类的指定公共构造函数;,括号里面不给参数返回无参构造方法
Object obj = cons2.newInstance(); //返回这个无参构造方法对应的学生类信息
// 根据指定的构造方法创建对象
/*得到的obj 与通过 Student s = new Student() 得到的结果是一样的 即 s==obj
只是obj是通过反射获取的,s是直接通过类构造得到的
*/
// 通过反射实现Student s = new Student("a",12,"123456")
//传入参数则获取带参构造方法,传入的参数是 带参构造方法中 数据类型.class;
Constructor<?> ss = c.getConstructor(String.class,int.class,String.class);
//这一步需要传入具体的参数
Object o1 = ss.newInstance("zhejiang",12,"12345");
// Constructor<?> cons3 = c.getDeclaredConstructors(); //返回一个指定的构造函数
}
}
3、反射获取成员变量并使用;
c.getField()
Field name = c.getField("name"); // 获取公有的成员变量name,不指定参数的话获取所有
Object obj1 = c.getConstructor().newInstance();
name.set(obj1,"zhejiang"); // 给name成员变量 赋值为 zhejiang ;
给对象obj1 的成员变量name赋值
package reflect;
import col.student.Student;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> c = Class.forName("col.student.Student");
var obj = c.getConstructor().newInstance();
var name = c.getDeclaredField("name");
name.setAccessible(true); // 私有成员变量设置暴力访问
name.set(obj,"zhejiang");
var age = c.getDeclaredField("age");
age.setAccessible(true);
age.set(obj,10);
}
}
4、反射获取成员方法并使用
getMethod()
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> c = Class.forName("col.student.Student");
var me = c.getMethod("method1"); //获取方法,传入的参数是方法名;
Object obj = c.getConstructor().newInstance();
me.invoke(obj);//表示obj实例对象调用me方法,如果me方法需要传入参数,将具体参数值写入括号
// 调用带参方法
var me1 = c.getMethod("method2",String.class,int.class); //获取方法,传入的参数是方法名;
Object obj1 = c.getConstructor().newInstance();
me1.invoke(obj1,"a",12); //如果方法带返回值,需要接收返回值
object o = me1.invoke(obj1,"a",12);
/* 等价于 Student s = new Student();
s.method1();*/
}
}
练习:给定一个集合ArrayList<Integer> 集合,在集合中添加字符串数据;
public class reflecttest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<Integer> array = new ArrayList<>();
array.add(10);
Class<? extends ArrayList> c= array.getClass();
Method m = c.getMethod("add", Object.class); //add方法的参数是object类型的
//通过反射获取原始的参数类型,然后加入
Object hello = m.invoke(array, "hello"); // 因为add的参数是object类型,所以可以添加字符串
}
}
练习2:通过配置文件运行类中的方法
class.txt 文件的内容
classname=col.student.Student methodname =study
package reflect;
import col.student.Student;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;
public class reflecttest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException {
Student s = new Student();
s.study();
/* 在class.txt 文件中配置
classname = xxx
methodname =xxx
*/
//1、加载数据
Properties prop =new Properties();
FileReader fr = new FileReader("class.txt");
prop.load(fr);
fr.close();
String classname = prop.getProperty("classname");//返回等号右边
String methodname = prop.getProperty("methodname");
//通过反射使用 反射调用指定类中的指定方法,如果需要修改类,只需要该配置文件
Class<?> c = Class.forName(classname);
Constructor<?> con= c.getConstructor();
Object o = con.newInstance();
Method me = c.getMethod(methodname);
me.invoke(o);
}
}