使用反射API

一、使用Class和反射创建类的对象

package ch15;

import java.lang.reflect.Constructor;

class Person {
    private String name;

    public Person() {
        this("匿名");
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public void run(int meters) {
        System.out.printf("%s跑了%d米%n", name, meters);
    }

    public String toString() {
        return "姓名:" + name;
    }

    private void helper() {
        System.out.println("私有的辅助方法");
    }
}

public class ObjectFactory {
    public static void main(String[] args) {
        if (args.length < 1) {
            System.exit(1);
        }
        try {
            Class<?> clz = Class.forName(args[0]);
            // 得到无参的共有构造方法
            Constructor noArgCons = clz.getConstructor();
            Object obj = noArgCons.newInstance();
            System.out.println(clz);
            System.out.println(obj);

            if (args.length > 1) {
                Class paramClz = args[1].getClass();
                // 得到一个参数的共有构造方法
                Constructor oneArgCons = clz.getConstructor(paramClz);
                obj = oneArgCons.newInstance(args[1]);
                System.out.println(obj);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二、使用反射调用对象的方法

package ch15;

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

class Person {
    private String name;

    public Person() {
        this("匿名");
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public void run(int meters) {
        System.out.printf("%s跑了%d米%n", name, meters);
    }

    public String toString() {
        return "姓名:" + name;
    }

    private void helper() {
        System.out.println("私有的辅助方法");
    }
}

public class ObjectFactory {
    public static void main(String[] args) {
        try {
            Class<?> clz = Class.forName("ch15.Person");
            // 得到一个参数的公有构造方法
            Constructor oneArgCons = clz.getConstructor(String.class);
            Object obj = oneArgCons.newInstance("张三");
            // 得到run方法对应的Method对象
            Method mth = clz.getMethod("run", int.class);
            // 调用run方法
            mth.invoke(obj, 800);

            // 得到helper方法对应的Method对象
            mth = clz.getDeclaredMethod("helper");
            // helper方法是私有方法,正常是不可调用的
            // 通过调用Method对象的setAccessible(true),将helper方法设置为可访问的
            mth.setAccessible(true);
            mth.invoke(obj);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、使用反射修改对象的字段

package ch15;

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

class Person {
    private String name;

    public Person() {
        this("匿名");
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public void run(int meters) {
        System.out.printf("%s跑了%d米%n", name, meters);
    }

    public String toString() {
        return "姓名:" + name;
    }

    private void helper() {
        System.out.println("私有的辅助方法");
    }
}

public class ObjectFactory {
    public static void main(String[] args) {
        try {
            Class<?> clz = Class.forName("ch15.Person");
            // 得到一个参数的公有构造方法
            Constructor oneArgCons = clz.getConstructor(String.class);
            Object obj = oneArgCons.newInstance("张三");
            System.out.println(obj);

            // 得到字段name
            Field f = clz.getDeclaredField("name");
            f.setAccessible(true);
            System.out.println(f.get(obj).toString());
            f.setAccessible(false);
            // name字段是私有的
            // 调用Field对象的setAccessible方法将其设置为可访问的
            f.setAccessible(true);
            // 设置name字段的值为李四
            f.set(obj, "李四");
            System.out.println(obj);
            f.setAccessible(false);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
posted @ 2021-03-07 15:15  xl4ng  阅读(61)  评论(0编辑  收藏  举报