java反射--Field用法实践与IllegalArgumentException构造

 

一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,“反射”指的是通过对象找到类。
 

简单来说:

java反射--Field用法实践与IllegalArgumentException构造_第1张图片 java反射机制简单例子

 

 

使用反射设置属性的例子:java反射--Field用法实践与IllegalArgumentException构造_第2张图片

代码:

实体类

package JavaCharacter;

/**
 * Created by jiangyayi on 19/5/24.
 */
public class Car {
    private String brand;
    private String color;
    private int maxSpeed;

    public Car() {
        System.out.println("init car!!");
    }

    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

    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;
    }
}

测试类

package JavaCharacter;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * Created by jiangyayi on 19/5/24.
 */
public class ReflexTest {

    public static Car initByDefaultConst() throws Throwable{

        //①通过类装载器获取Car类对象
        ClassLoader loader =Thread.currentThread().getContextClassLoader();
        //loadclass可以通过getclass来获取地址
        Class clazz=loader.loadClass("JavaCharacter.Car");


        //②获取类的默认构造器对象并通过它实例化Car
        Constructor constructor=clazz.getDeclaredConstructor((Class[]) null);
        Car car = (Car) constructor.newInstance();
        //③通过反射方法设置属性
        Method setBrand = clazz.getMethod("setBrand", String.class);
        setBrand.invoke(car, "红旗CA72");
        Method setColor = clazz.getMethod("setColor", String.class);
        setColor.invoke(car, "黑色");
        Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
        setMaxSpeed.invoke(car, 200);
        return car;
    }


    public static void main(String args[]) throws Throwable {
        Car car = initByDefaultConst();
        System.out.println(car.getClass()); //打印类
        car.introduce();

        ReflexTest test =new ReflexTest();

        System.out.println(test.getClass()); //使用实例的getClass方法找到类

        System.out.println("-----------cls------------"); //打印类

        Class cls=test.getClass(); //取得class对象

        System.out.println(cls.getClass()); //打印类
        System.out.println(cls.getName());  //使用反射机制打印名称

    }
}

 

类Field定义:

java反射--Field用法实践与IllegalArgumentException构造_第3张图片

http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

Field是一个类,位于java.lang.reflect包下。在Java反射中Field类描述的是类的属性信息,功能包括:

1.获取当前对象的成员变量的类型
2.对成员变量重新设值

方法:

1、public Field[] getFields() throws SecurityException

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共public字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组。
getDeclaredFields(): 获取类中所有的属性(public、protected、default、private),但不包括继承的属性,返回 Field 对象的一个数组

2、public Field getField(String name throws NoSuchFieldException, SecurityException

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 name 参数是一个 String,用于指定所需字段的简称。

要反映的字段由下面的算法确定。设 C 为此对象所表示的类:

  1. 如果 C 声明一个带有指定名的公共字段,则它就是要反映的字段。
  2. 如果在第 1 步中没有找到任何字段,则该算法被递归地应用于 C 的每一个直接超接口。直接超接口按其声明顺序进行搜索。
  3. 如果在第 1、2 两步没有找到任何字段,且 C 有一个超类 S,则在 S 上递归调用该算法。如果 C 没有超类,则抛出 NoSuchFieldException

 

3、public Field[] getDeclaredFields() throws SecurityException

 

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。包括公共public、保护protected、默认(包)访问和私有private字段,但不包括继承的字段。 返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。

 

4、public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 name 参数是一个 String,它指定所需字段的简称。注意,此方法不反映数组类的 length 字段。

 

方法摘要:

java反射--Field用法实践与IllegalArgumentException构造_第4张图片


常见错误
1.set(Object obj, Object value) 时,新value和原value的类型不一致导致,如下:无法转换类型导致 java.lang.IllegalArgumentException(注意:反射获取或者修改一个变量的值时,编译器不会进行自动装/拆箱,所以int 和Integer需手动修改)


2.set(Object obj, Object value) 时,变量访问检查导致的 IllegalAccessException。由于 Field 继承自 AccessibleObject , 我们可以使用 AccessibleObject.setAccessible() 方法告诉安全机制,这个变量可以访问即可解决,如field.setAccessible(true)。

java反射--Field用法实践与IllegalArgumentException构造_第5张图片

java反射--Field用法实践与IllegalArgumentException构造_第6张图片

3、getField(String name) 或getFields() 获取非 public 的变量,编译器会报 java.lang.NoSuchFieldException 错。

java反射--Field用法实践与IllegalArgumentException构造_第7张图片

你可能感兴趣的:(java-JVM)