欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Java编程中的反射在Android开发中的应用

程序员文章站 2022-07-11 18:39:06
反射定义 “反射”(reflection)能够让运行于jvm中的程序检测和修改运行时的行为。 为何需要反射 反射带来的好处包括:   &...

反射定义

“反射”(reflection)能够让运行于jvm中的程序检测和修改运行时的行为。
为何需要反射

反射带来的好处包括:

  •     在运行时检测对象的类型。
  •     动态构造某个类的对象。
  •     检测类的属性和方法。
  •     任意调用对象的方法。
  •     修改构造函数、方法、属性的可见性。

反射方法method
getdeclaredmethod方法

声明如下:

public method getdeclaredmethod(string name, class<?>... parametertypes) throws nosuchmethodexception, securityexception

解释:

    返回一个method对象,该对象反映此class对象所表示的类或接口的指定已声明方法。
    1. name : 是一个string,它指定所需方法的简称。
    2. parametertypes:是一个class对象的变长数组,它按声明顺序标识该方法的形参类型。

注意:
getdeclaredmethod获取该类声明的public方法或者protected方法,但是不包括继承的方法。
getmethod方法

声明如下:

public method getmethod(string name, class<?>... parametertypes) throws nosuchmethodexception, securityexception

解释:

    返回一个method对象,该对象反映此class对象所表示的类或接口的指定公共成员方法。
    1. name : 是一个string,它指定所需方法的简称。
    2. parametertypes:是一个class对象的变长数组,它按声明顺序标识该方法的形参类型。

参数解释

name参数就不需要解释了,就是调用类的方法名称。

可能很多同学刚接触这个方法的时候,会对parametertypes参数产生疑问,例如这个参数为什么是class泛型变长数组,其实举个例子就很好理解了。

假设我们要反射的方法有4个参数,函数原型如下:

public void printinfo(string str, int inum, double dnum, long i);

那我们通过返回获取这个method对象的时候,传的parametertypes如下所示:

getmethod("printinfo", string.class, int.class, double.class, long.class);


所以,parametertypes其实就是对方法形参的类型抽象。
invoke方法

声明如下:

public object invoke(object obj, object... args) throws illegalaccessexception, illegalargumentexception, invocationtargetexception

解释:

    method类的invoke(object obj, object… args)方法接收的参数必须为对象。其中:
    1. obj : 从中调用底层方法的对象。
    2. args :用于方法调用的参数。

android 反射应用

我们知道,android有些类是没有在sdk中开放的,例如你需要获取系统属性,需要调用到systemproperties类的get方法,但是这个类并没有在sdk中公开,我们可以在android源码中查看一下这个类:

package android.os;

import java.util.arraylist;

import android.util.log;


/**
 * gives access to the system properties store. the system properties
 * store contains a list of string key-value pairs.
 *
 * {@hide}
 */
public class systemproperties
{
  // 省略具体实现代码
  /**
 * get the value for the given key.
 * @return an empty string if the key isn't found
 * @throws illegalargumentexception if the key exceeds 32 characters
 */
 public static string get(string key) {
  if (key.length() > prop_name_max) {
   throw new illegalargumentexception("key.length > " + prop_name_max);
  }
  return native_get(key);
 }
}


可以看到,这个前面有一个@hide标签,所以这个类是没法直接在代码中调用的。

但是,在android应用中,很多时候我们需要获取到手机类型属性(ro.product.model)。所以,这个时候,我们就需要在应用层反射systemproperties类,调用get方法。具体实现源码如下:

import java.lang.reflect.invocationtargetexception;
import java.lang.reflect.method;

import android.util.log;

public class systemproperties {
 public static string get(string key) {
  string value = "";
  class<?> cls = null;

  try {
   cls = class.forname("android.os.systemproperties");
   method hidemethod = cls.getmethod("get", string.class);
   object object = cls.newinstance();
   value = (string) hidemethod.invoke(object, key);
  } catch (classnotfoundexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  } catch (nosuchmethodexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  } catch (instantiationexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  } catch (illegalaccessexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  } catch (illegalargumentexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  } catch (invocationtargetexception e) {
   log.e("zhengyi.wzy", "get error() ", e);
  }

  return value;
 }

}