夯实基础之Java 反射

开始之前

反射,一直是我的一块心病,必须啃下来。
在研究插件化,在插件内部启动插件自身的组件,如:Activity ,Service , BroadcastReceiver等等。由于在插件内部没有上下文环境是无法启动组件的,必须依赖宿主的代理组件来代理插件组件。而通过代理组件间接执行插件中组件的OnCreate, OnStartCommand , onReceive方法,而执行这些方法都需要使用反射来获取类对象,进而执行方法。

如下代码中,在代理 ProxyActivity中,通过反射拿到插件Activity,进而执行onCreate方法

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate: ");
        String className = getIntent().getStringExtra(Constants.CLASS_NAME);

        //真正的加载 插件里面的Activity

        // 动态获取className , 不能写死(包名+类名)
        // String className = null;
        try {
            // 拿到插件包中的第一个Activity
            // 由于插件是直接以APK文件存在于sd卡,并没有加载过,所以需要类加载器加载           
            Class pluginClass = getClassLoader().loadClass(className);

            // 实例化插件包中的Activity
            Constructor constructor = pluginClass.getConstructor(new Class[]{});
            Object pluginActivity = constructor.newInstance(new Object[]{});

            // 强转为ActivityInterface
            activityInterface = (ActivityInterface) pluginActivity;

            // 将宿主的环境注入给插件
            activityInterface.insertAppActivity(this);

            // 执行插件onCreate 方法
            // 可以从宿主 携带参数 给 插件
            Bundle bundle = new Bundle();
            bundle.putString("fromAppInfo", "我是来自宿主的一条信息");
            // 间接调用pluginActivity的onCreate方法
            activityInterface.onCreate(bundle);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

通过反射构建对象

测试类

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    private void introduce(String name, int age) {
        System.out.println(String.format("introduce 自我介绍: 我是 %s , 正少年 %d", name, age));
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

1. 类的构造方法无参数

如果拿不到类的全限定名(包名+类名),可以通过以下方式反射构建,

    @Test
    public void reflectTest2() {
        try {
            Person personObj = (Person) Class.forName("com.purang.stander.reflect.Person").newInstance();
            System.out.println(personObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出:

com.purang.stander.reflect.Person@722c41f4

如能拿到全限定名(包名+类名),可以通过

    @Test
    public void reflectTest3() {
        try {
            Person person1 = Person.class.newInstance();
            System.out.println(person1.toString());
            
            Person person2 = person1.getClass().newInstance();
            System.out.println(person2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出:

com.purang.stander.reflect.Person@722c41f4
com.purang.stander.reflect.Person@5b80350b

2. 类的构造方法有参数

    @Test
    public void reflectTest4() {
        Class[] classes = {String.class, int.class};
        try {
            // @param parameterTypes :the parameter array
            // @param initargs 构造对象的参数
            Person person = (Person) Class.forName("com.purang.stander.reflect.Person").getConstructor(classes).newInstance("城南一霸贾十七", 18);
            System.out.println(person.toString());
        } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

通过forName加载到类的加载器,
输出:

Person{name='城南一霸贾十七', age=18}

反射获取类方法,并执行

    @Test
    public void reflectTest5() {
        Class[] classes = {String.class, int.class};
        try {
            Person person = (Person) Class.forName("com.purang.stander.reflect.Person").newInstance();
            /**
             * getMethod() , getMethods() / getFields() , getField() 只能获取public 修饰的方法和属性
             * getDeclaredMethod() , getDeclaredMethods() / getDeclaredField(), getDeclaredFields() 可以获取私有方法和属性
             */
            Method introduceMethod = person.getClass().getDeclaredMethod("introduce", classes);
            introduceMethod.setAccessible(true);
            introduceMethod.invoke(person, "城南一霸贾十七", 18);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出:

introduce 自我介绍: 我是 城南一霸贾十七 , 正少年 18

参考:
https://www.cnblogs.com/zyxsblogs/p/11225233.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值