hello_dakewang

导航

java反射机制

1,相关java基础知识

  java语言允许通过程序化的方式间接对class进行操作,Class文件由类加载器装载后,在jvm中形成一份描述Class结构的元信息,通过该元信息对象可得到class的结构信息,如构造函数,属性,方法等。java允许用户借由这个与class相关的元信息对象间接调用class对象功能,这就为使用程序化操作class对象开辟途径。

  car实例

/**
* Created by qiqi on 2018/11/20 11:10
*/
@Data //lombok方法,免写构造函数,get,set方法
public class Car {
private String brand;
private String color;
private int maxSpeed;

public void introduce() {
System.out.println("brand:"+brand+",color:"+color+",maxSpeed:"+maxSpeed);
}
}
一般情况下我们会通过传统的方法实现car 实例
Car car = new Car();
car.setBrand("红旗");
car.setColor("黑色");
car.setMaxSpeed(300);
Car car = new Car("红旗","黑色",300);

下面我们通过java反射机制以一种间接的方式来操控目标类:
import com.fivezerotwo.dto.Car;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
* 反射原理实例
* Created by qiqi on 2018/11/20 10:47
*/
public class ReflactTest {

public static Car inintByDefaultConst() throws Throwable{
//1.通过类装载器获取当前线程calssloader
ClassLoader loader = Thread.currentThread().getContextClassLoader();
//限定名称
Class clazz = loader.loadClass("com.fivezerotwo.dto.Car");

//2.获取类默认构造函数,并通过它实现car实例 相当于Car car = new Car();
Constructor constructor = clazz.getDeclaredConstructor();
Car car = (Car) constructor.newInstance();

//3.通过反射方法设置属性
Method setBrand = clazz.getMethod("setBrand", String.class);
setBrand.invoke(car,"红旗");
Method setColor = clazz.getMethod("setColor", String.class);
setColor.invoke(car,"黑色");
Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
setMaxSpeed.invoke(car,300);
return car;
}

public static void main(String[] args) throws Throwable {
Car car = inintByDefaultConst();
car.introduce();
}
}
运行以上程勋控制台打印:
brand:红旗,color:黑色,maxSpeed:300

这说明我们完全可以编程的方式来调用class的各个功能,与通过构造函数和方法调用类的功能是完全一样的,只不过前者是间接调用,后者是直接调用。
在reflectTest中有几个重要的反射类,分别是ClassLoader,Constructor,Class, Method通过这些反射方法就可操作class类。
在程序中黑色加粗信息就是通过反射方法操控的元信息,我们可以把这些元信息以配置文件的形式提供,这样我们就可以使用java语言的反射功能编写一段通用代码,对类的实例化及功能的调用。

2,类装载器ClassLoader

a.类装载器的工作原理
类装载器就是寻找类的节码文件并构造类在JVM内部表示对象的组件,在Java中,类装载器把类装入JVM必须经过一下几个步骤:
(1)装载:查找和导入Class文件;
(2)链接:执行校验,准备和解析步骤,其中解析步骤可以省略
  • 校验:检查加载的Class文件数据准确性;
  • 准备:给类的静态变量分配存储空间;
  • 解析:将符号引用转换为直接引用;
(3)初始化:对静态变量,静态代码执行初始化工作;

JVM在运行时会产生3个ClassLoader:
  • 根装载器:负责装载jre的核心类库,不是ClassLoader的子类,使用c++编写,因而在Java中看不到它;
  • ExtClassLoader(扩展类装载器):负责装载jre扩展目录ext的jar类包,ClassLoader的子类;
  • AppClassLoader(应用类装载器):负责ClassPath路径下的类包, ClassLoader的子类;
/**
* ClassLoader类加载器
* Created by qiqi on 2018/11/20 14:21
*/
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
System.out.println("current loader:"+ classLoader);
System.out.println("parent loader:"+ classLoader.getParent());
System.out.println("grandparent loader:"+ classLoader.getParent().getParent());

}
}

控制台输出:

根装载器在Java中k访问不到,所以返回为null。

b.ClassLoader的重要方法:

3,Java的反射机制:

 


posted on 2018-11-20 15:48  hello_dakewang  阅读(138)  评论(0编辑  收藏  举报