类加载器与反射

Posted zhangrui0328

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类加载器与反射相关的知识,希望对你有一定的参考价值。

当程序使用类的时候,类会被加载到内存中。整个过程分三步:

1.加载:将类文件加载到内存的堆中中,创建字节码文件对象。

2.连接,验证文件内部结构是否正确。

   准备:为静态成员分配内存,并设置默认初始化值

    解析:将类的二进制数据的符号引用换为直接引用

3.初始化

类加载器组成:

 Bootstrap ClassLoader 根类加载器:负责java核心类的加载

 Extension ClassLoader 扩展类加载器:负责jre的扩展目录的jar包的加载

 System ClassLoader 系统类加载器:负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

反射是不通过对象直接调用类的一切属性和方法的方式。

步骤:(1)获取class对象

   (2)通过class对象获取方法或属性

     (3) 执行方法,修改属性

获取Class对象的三种方式 (1)Class c=Class.forName(路径);(2)对象.getClass (3)类名.class

获取方法的方式(1)获取构造方法 getConstructor()(2)获取普通方法getMethod()(3)获取一切方法(包括私有修饰的)getDeclaredMethod(4)获得一切构造方法与获得一般方法类同,也是加上Declared修饰

执行方法用invoke(),但若要执行私有方法,需要先将获得的私有方法setAccesible(true),才能执行。若修改私有成员变量也需要这样。

获取成员变量的方法  getField()(获取私有的成员变量与获取私有方法的方式类似),修改成员变量方法:set()。

下面是一个例子:

public class Demo01 {
	public static void main(String[] args) throws Exception {
		ti5();
	}
//	ArrayList<Integer> list = new ArrayList<Integer>(); 
//	这个泛型为Integer的ArrayList中存放一个String类型的对象
	public static void ti1() throws Exception, Exception{
		ArrayList<Integer> list = new ArrayList<Integer>(); 
		Class c=list.getClass();
		Method method=c.getMethod("add",Object.class);
		method.invoke(list,"你好");
		System.out.println(list);
	}
	//用反射去创建一个对象,有2种方式,尽量用代码去体现
	public static void ti2() throws Exception{
		Class c=Class.forName("com.java.demo.Person");
		Object oj=c.newInstance();
		System.out.println(oj);
		Constructor con=c.getConstructor(String.class,int.class,String.class);
		Object obj=con.newInstance("张三",18,"男");
		System.out.println(obj);
	}
	//编写一个类,增加一个实例方法用于打印一条字符串。并使用反射手段创建该类的对象, 并调用该对象中的方法。
	public static void ti3() throws Exception{
		Class c=Class.forName("com.java.demo.Person");
		Object obj=c.newInstance();
		Method method=c.getMethod("run");
		method.invoke(obj);
	}
	//定义一个标准的JavaBean,名叫Person,包含属性name、age。
//	使用反射的方式创建一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置,
//	不使用setAge方法直接使用反射方式对age赋值。
	public static void ti4() throws Exception{
		Class c=Class.forName("com.java.demo.Person");
		Constructor con=c.getConstructor(String.class,int.class,String.class);
		Object obj=con.newInstance("张三",14,"男");
		System.out.println(obj);
		Method method=c.getMethod("setName", String.class);
		method.invoke(obj, "李四");
		System.out.println(obj);
		Field field=c.getDeclaredField("age");
		field.setAccessible(true);
		field.set(obj, 15);
		System.out.println(obj);
	}
	public static void ti5() throws IOException, Exception{
		Properties pro=new Properties();
		FileReader fr=new FileReader("pro.properties");
		pro.load(fr);
		String demoName=pro.getProperty("DemoName");
		Class c=Class.forName(demoName);
		Object obj=c.newInstance();
		Method method=c.getMethod("run");
		method.invoke(obj);
		
	}
}

 

以上是关于类加载器与反射的主要内容,如果未能解决你的问题,请参考以下文章

面试常问的类加载器与双亲委派模型

Java技术专题深度分析加载器与双亲委派机制「 入门篇」

JVM技术专题针对于加载器与双亲委派机制分析和研究指南 「 入门篇」

说下类加载器与类加载?加载的信息放在哪个区域?

浅谈类加载器与类加载案例解析

JVM类加载器与类加载过程