反射在android中的应用

1.前言:

  • 反射:动态加载一个由我们指定的类,获取其所有的内容(成员变量、成员函数、构造函数),简而言之反射就是对一个类进行了全面的解剖。同时,反射增强了一个程序的扩展性。
  • android中目前接触使用场景:
    1. 兼容平台。android现在主流平台是基于高通、MTK,当我们开发一些系统内置app时会遇到平台的差异性,比如MTK开放的NVRAMgent在高通平台就没有,这就需要我们兼容平台合作的公司可能就给你几个接口让你去调用,这时反射技术动态加载就派上了用场。
    2. @hide隐藏的方法。Google之所以使用@hide标记主要是考虑到安全性以及此方法或者类目前还不完善后续的API可能会开放。想要调用@hide标记的方法通常我们使用反射技术来绕开权限实现调用,当然你有android源码的话可以在源码环境下import导包就可以调用;或者将@hide标记删除重新编译一份SDK。这个标记的作用更多的是方便硬件厂商做闭源的二次开发。

2.反射三步走

  • 获取class对象,即获取到指定类名称的字节码文件对象。
  • 实例化对象,为获取构造函数、成员变量、成员函数作准备。
  • 访问属性、调用函数、调用构造函数创建的对象。
2.1获取class对象

a. 指定类名后通过forName方法获取class对象,这种方式只要有名称即可,更方便,扩展性更强。执行静态块、不执行动态构造块。

     Class<?> aClass=Class.forName("com.example.reflect.Test");

b. 通过类名.class方式获得。不执行静态块和动态构造块语句。

     Class<?> aClass=Test.class;

c. 对象名.getClass()方法获取。需要创建对象,静态块和动态构造块均会执行。

    Test test=new Test();
    Class<?> tClass=test.getClass();
2.2获取反射类的三个重要信息

在获取到class对象后,接着无非就是获取类的属性、方法、构造函数来为对象所用。下面介绍这三个重要信息的获取。

  • 构造函数获取
    在java中构造函数创建了对象,为对象分配了内存空间、并初始化了一些属性。反射获取构造函数能使我们动态的创建对象。
    //根据指定的参数获取匹配的构造函数,仅能获取public构造函数
    Constructor getConstructor(Class[] params);
    //根据指定的参数获取匹配的构造函数,能获取所有构造函数
    Constructor getDeclaredConstructor(Class[] params);
    //不明确构造函数参数列表时获取所有的public构造函数
    Constructor[] getConstructors();
    //不明确构造函数参数列表时获取所有的构造函数
    Constructor[] getDeclaredConstructors();
  • 成员函数获取
    构造函数创建了对象,获取成员函数使得对象具有行为的特征,成员函数的调用执行才是绝大多数对象存在的证据和意义。成员函数获取和构造函数的获取十分相近,权限意义也可以类似理解。
   //根据指定函数名称name、参数列表获取其方法仅public修饰的    
    Method getMethod(String name, Class[] params);
    //根据指定函数名称name、参数列表获取其所有方法
    Method getDeclaredMethod(String name, Class[] params);
    //不明确成员函数时获取所有public修饰的方法
    Method[] getMethods();
    //不明确成员函数时获取所有方法
    Method[] getDeclaredMethods();
  • 成员变量获取
    成员变量,我们经常叫做一个对象的域。从内存的角度来说,构造函数和成员函数都仅仅是Java对象的行为或过程,而成员变量则是真正构成对象本身的细胞和血肉。简单的说,就是成员变量占用的空间之和几乎就是对象占用的所有内存空间。
    //根据指定的name获取public修饰的成员变量
    Field getField(String name);
    //根据指定的name可以获取private修饰的成员变量    
    Field getDeclaredField(String name);
    //获取所有的public成员变量    
    Field[] getFields();
    //获取所有的成员变量        
    Field[] getDeclaredFields();
2.3访问和调用需要获取的信息

我们获取的信息其实都是属于类的,而不是对象。对于类的信息提取,其实并不涉及到对象内存,在程序编译完成的那一刻起,一切都已经是确定的了。因此,它并不能算“动态”。而如何对对象内存进行操作和访问,才是“动”的真正含义。

  • 创建对象
    Constructor支持泛型,也就是它本身应该是Constructor< T >。这个类有一个public成员函数,T newInstance(Object… args),其中args为对应的参数。我们正是通过它来实现创建对象。
    Object object=newInstance(args);
    //Test t=(Test)newInstance(args);
  • 调用成员函数
    invoke是调用执行反射的方法从属于Method 类,其第一个参数为对象,后面为反射函数传入的参数值,如果反射函数有返回类型值需要转为对应类型;如果反射函数为static修饰的,第一参数可以传入null,因为static修饰的函数属于类而不是对象,因此也不用创建对象。
Object invoke(Object receiver,  arg1,arg21,....,agrs);
  • 调用成员变量
    Field类有两个public方法,分别对应读与写,如下。object参数需要传入的对象,原理类似于成员方法需要指明对象一样。如果是静态属性,此值同样可以为null。
Object get(Object object)
void set(Object object, Object value)
  • 参考:

http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果在Android 4.4系统无法通过反射找到StorageManager的format方法,您可以尝试使用Android提供的另一种方式来格式化外置SD卡。以下是一种可行的方法: 1. 在AndroidManifest.xml文件添加以下权限: ```xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 2. 在您的Activity或Fragment使用以下代码进行格式化: ```java import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_FORMAT_SD_CARD = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); formatSdCard(); } private void formatSdCard() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Intent intent = new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS); startActivityForResult(intent, REQUEST_CODE_FORMAT_SD_CARD); } else { Uri uri = Uri.parse("file:///mnt/sdcard"); Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, uri); sendBroadcast(intent); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_FORMAT_SD_CARD) { // 处理格式化完成后的操作 } } } ``` 3. 当您的应用程序运行时,它将打开设备的存储设置页面,供用户手动格式化SD卡。当用户完成格式化后,您可以在onActivityResult方法处理格式化完成后的操作。 请注意,这种方法依赖于设备的存储设置页面,因此在不同的设备上可能会有所不同。确保在进行格式化之前备份重要数据,并测试代码以确保其在目标设备上正常工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值