Begin

反射机制是在运行状态中:
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;

反射提供的功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。

获取反射对象

package reflect;

public class reflectDemo1 {
    public static void main(String[] args) {
        // 获取反射对象(反射入口)
        // 1. Class.forName(全类名)
        try {
            Class<?> perClazz1 = Class.forName("reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 2. 类名.class
        Class<?> perClazz2 = reflect.Person.class;
        // 3. 对象.getClass()
        Person per = new Person();
        Class<?> perClazz3 = per.getClass();
    }
}
package reflect;

public class Person implements MyInterface {
    public Person() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public static void staticMethod() {
        System.out.println("staticMethod");
    }

    public Person(int id) {
        this.id = id;
    }

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private void privateMethod() {
        System.out.println("privateMethod");
    }

    private void privateMethod(String s) {
        System.out.println(s);
    }

    private int id;
    private String name;
    private int age;

    @Override
    public void interfaceMethod() {
        System.out.println("interfaceMethod");
    }
}

Java泛型中的通配符

  1. <?>称为非受限通配,其实就相当于 <? extends Object>,可以表示任何一种对象类型
  2. <? extends T>称为受限通配,表示需要的是T或者T的子类型
  3. <? super T>称为下限通配,表示需要的是T的父类型

断言

  1. assert <boolean表达式>如果<boolean表达式>为 true,则程序继续执行。如果为 false,则程序抛出 AssertionError,并终止执行。
  2. assert <boolean表达式> : <错误信息表达式>
    如果 <boolean表达式>true,则程序继续执行。

如果为 false,则程序抛出 java.lang.AssertionError,并输入 <错误信息表达式>
<错误信息表达式>表示一个基本类型、表达式或者是一个 Object,用于在失败时输出错误信息。

获取Class的内容

        // Class入口
        Class<?> perClazz1 = null;
        try {
            perClazz1 = Class.forName("reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 获取所有公共方法(本类及父类,接口中的方法且符合访问修饰符规则)
        assert perClazz1 != null;
        Method[] methods = perClazz1.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        // 获取所有接口
        Class<?>[] interfaces = perClazz1.getInterfaces();
        for (Class<?> inter : interfaces) {
            System.out.println(inter);
        }

        // 获取所有父类(单继承)
        Class<?> superclass = perClazz1.getSuperclass();
        System.out.println(superclass);

        // 获取所有构造方法
        Constructor<?>[] constructors = perClazz1.getConstructors();

        // 获取所有公共属性(包括父类,符合访问修饰符)
        Field[] fields = perClazz1.getFields();

        // 获取当前类的所有方法(当前类,包括private)
        Method[] methods1 = perClazz1.getDeclaredMethods();

        // 获取当前反射所代表类(接口)的对象的实例

        Object instance = null;
        try {
            instance = perClazz1.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

        Person per = (Person) instance;
        assert per != null;
        per.interfaceMethod();

操作对象

        // 操作获取实例的对象
        per.setAge(6);
        per.setName("zs");

        // 操作属性
        Field idField = perClazz1.getDeclaredField("id");
        // 修改属性的访问权限
        idField.setAccessible(true);
        idField.set(per, 1);
        // 操作方法
        Method method = perClazz1.getDeclaredMethod("privateMethod", null);
        method.setAccessible(true);
        method.invoke(per, null);
        // 有参
        method = perClazz1.getDeclaredMethod("privateMethod", String.class);
        method.setAccessible(true);
        method.invoke(per, "zs");

操作构造方法

        // 操作构造方法
        Constructor<?>[] constructors1 = perClazz1.getDeclaredConstructors();
        for(Constructor<?> constructor: constructors1)
            System.out.println(constructor);
        // 获取指定构造方法(反射中基本类型和包装类型不同)
        // 如果是private要用perClazz1.getDeclaredConstructor()
        Constructor<?> constructor = perClazz1.getConstructor(int.class);
        System.out.println(constructor);
        // 产生对象
        Person instance1 = (Person) constructor.newInstance(10);

通过反射运行配置文件内容

配置文件class.txt:

className = reflect.Student
methodName = staticMethod
        Properties prop = new Properties();
        prop.load(new FileReader("class.txt"));

        String classname = prop.getProperty("classname");
        String methodname = prop.getProperty("methodname");

        Class<?> perClazz = null;
        try {
            perClazz = Class.forName(classname);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Method method = perClazz.getMethod(methodname);
        method.invoke(perClazz.newInstance());

越过泛型检查

        ArrayList<Integer> list = new ArrayList<>();
        list.add(123);
        list.add(3);
        list.add(2);
        // list.add("zs") ;

        Class<?> listClazz = list.getClass();
        Method method = listClazz.getMethod("add", Object.class);
        method.invoke(list, "zs");
        System.out.println(list);

通用的set方法

public class PropertyUtil {
    public static void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Class<?> clazz = obj.getClass();
        Field field = clazz.getDeclaredField(propertyName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

调用:

        Person per = new Person();
        PropertyUtil.setProperty(per, "name", "zs");

动态一维数组

        Scanner in = new Scanner(System.in);
        System.out.println("Input Type:");
        String type = in.nextLine();
        System.out.println("Input num:");
        int num = in.nextInt();
        Class<?> c = Class.forName(type);
        Object arr = Array.newInstance(c, num);

        Array.set(arr, 0, "zs");
        System.out.println(Array.get(arr, 0));

动态二维数组

        Class c = Integer.class;
        int[] dim = {4, 4};
        Object o = Array.newInstance(c, dim);
        // 第二行
        Object arr2 = Array.get(o, 2);
        // 第二行第一列赋值
        Array.set(arr2, 1, 666);
        System.out.println(Array.get(arr2, 1));



扫一扫在手机打开当前页