编写一个简单示例开始探访Java反射机制的征程,通过比较传统方法以及反射机制创建类实例的不同,来介绍Java反射机制的原理
首先创建一个Bean :Car类,拥有两个构造函数,一个方法以及三个属性
- public class Car {
- private String brand;
- private String color;
- private int maxSpeed;
- //1.默认构造函数
- public Car(){
- System.out.println("init car!!");
- }
- //2.带参构造函数
- public Car(String brand,String color,int maxSpeed){
- this.brand = brand;
- this.color = color;
- this.maxSpeed = maxSpeed;
- }
- //3.未带参的方法
- public void introduce() {
- System.out.println("brand:"+brand+";color:"+color+";maxSpeed:"+maxSpeed);
- }
- public String getBrand() {
- return brand;
- }
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- public int getMaxSpeed() {
- return maxSpeed;
- }
- public void setMaxSpeed(int maxSpeed) {
- this.maxSpeed = maxSpeed;
- }
- }
在传统的调用方法中,我们是使用构造函数设置属性或者使用set方法设置属性
1. 构造函数方法:
- Car car = new Car(“红旗轿车”, “黑色”, “180”);
2. Set方法:
- Car car = new Car();
- car.setBrand(“红旗轿车”);
实例代码如下:
- public class ReflectTest {
- /**
- * 通过默认的构造方法来实例化car,并获取car的相关属性。
- * @return
- * @throws Throwable
- */
- public static Car initByDefaultConst() throws Throwable
- {
- //1.通过类装载器获取Car类对象
- //使用当前线程获取类加载器
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- //通过使用全限定类名来装载Car类对应的反射实例
- Class clazz = loader.loadClass("cn.lovepi.chapter02.reflect.Car");
- //2.获取类的默认构造器对象并实例化Car
- //通过Car的反射类对象来获取Car的构造函数对象.
- Constructor cons = clazz.getDeclaredConstructor((Class[])null);
- //通过构造函数对象的newInstance方法来实例化Car对象,其效果等同与new Car()
- Car car = (Car)cons.newInstance();
- //3.通过反射方法设置属性
- //通过Car的反射类对象的getMethod方法来获取相应的set方法对象.
- //第一个参数是目标class的方法,第二个参数是方法注册的对象类型
- Method setBrand = clazz.getMethod("setBrand",String.class);
- //通过invoke方法来调用目标类的方法
- //该方法的第一个参数是操作的目标类示例,第二个参数则是目标方法的主参
- setBrand.invoke(car,"奔驰");
- Method setColor = clazz.getMethod("setColor",String.class);
- setColor.invoke(car,"黑色");
- Method setMaxSpeed = clazz.getMethod("setMaxSpeed",int.class);
- setMaxSpeed.invoke(car,200);
- return car;
- }
- /**
- * 获取类的带有参数的构造器对象来实例化car并设置相关的属性
- * @return
- * @throws Throwable
- */
- public static Car initByParamConst() throws Throwable{
- //1.通过类装载器获取Car类对象
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- Class clazz = loader.loadClass("cn.lovepi.chapter02.reflect.Car");
- //2.获取类的带有参数的构造器对象
- Constructor cons = clazz.getDeclaredConstructor(new Class[]{String.class,String.class,int.class});
- //3.使参数的构造器对象实例化Car
- Car car = (Car)cons.newInstance(new Object[]{"宝马","红色",180});
- return car;
- }
- public static void main(String[] args) throws Throwable {
- Car car1 = initByDefaultConst();
- Car car2 = initByParamConst();
- car1.introduce();
- car2.introduce();
- }
- }
通过以上示例,可以看到我们完全可以通过编程的方式来调用class的特定功能,这和直接通过构造函数和方法来调用类的功能的效果的内容是一致的。只不过前者是间接调用,而后者是直接调用罢了。
在刚才示例类中我们使用了几个重要的反射类:
ClassLoader:类加载器
Class:类对象
Constructor:类的构造函数
Method:类方法
通过这些反射类就可以间接调用目标class的某些功能。