作为Android开发你必须知道的Java反射机制

一.什么是反射机制?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制.


二.我们需要知道哪些东西?

反射中我们最常接触到的类大致有一下几个:

  • Class:
    Class对象是一个特殊的对象,是用来创建其它对象的对象(这里的其他对象就是指:java类的实例.其实Class对象就是java类编译后生成的.class文件,它包含了与类有关的信息.
  • Field:
    Field字段提供有关和动态访问的信息,类或接口的单个字段。反射的字段可能
    是类(静态)字段或实例字段.
  • Method:
    Method方法提供了关于单个方法的信息和访问在类或接口上。反射的方法可能是类方法或者一个实例方法(包括一个抽象的方法).
  • Constructor:
    Constructor提供了关于某类的构造方法的所需信息.

三.我们要掌握哪些方法呢?

  • 获取Class对象的几个方法:
    (1) 类名.class;
    (2) Class.forName(类路径);
    (3) 对象.getClass();
    三个方法的区别是方法一不执行静态块和动态构造块,方法二执行静态块、不执行动态构造块,方法三需要创建对象,静态块和动态构造块均会执行.
  • 获取类属性的几个方法:
    (1) persionClass.getField(方法的名称);
    (2) persionClass.getFields();
    (3) persionClass.getDeclaredField(方法的名称);
    (4) persionClass.getDeclaredFields();复制代码
    里面getField和getFields只能获取到public修饰的字段,getDeclaredField和getDeclaredFields可以获取到所有的字段.其中以s结尾的是获取所有的字段返回的是一个Field 的数组.
  • 获取类方法的几个方法:
    (1) persionClass.getMethod(方法的名称);
    (2) persionClass.getMethods();
    (3) persionClass.getDeclaredMethod(方法的名称);
    (4) persionClass.getDeclaredMethods();复制代码
    getMethod和getMethods只能获取到public修饰的方法名称,getDeclaredMethod和getDeclaredMethods可以获取到所有的方法.
  • 获取构造函数的几个方法:
    (1) persionClass.getConstructor(可变参数集合);
    (2) persionClass.getConstructors();
    (3) persionClass.getDeclaredConstructor(方法的名称);
    (4) persionClass.getDeclaredConstructors();复制代码
    getConstructor和getConstructors只能获取到public修饰的方法名称,getDeclaredConstructor和getDeclaredConstructors可以获取到所有的方法.
  • 创建对象的方法:

    (1) Constructor.newInstance(可变参数);
    
    eg:Persion p = (Persion)constructor.newInstance("1");复制代码
  • 设置属性值:
    (1) field.set(Objkect obj,Object value);
    (2) field.setInt(Objkect obj,int value);
    ...
    (n) file.setLong(Objkect obj,long value);复制代码
  • 获取属性对象:

    (1) field.get(Object);
    
    eg:Person p = (Persion)filed.get(对象);复制代码

    这里要注意了如果字段的修饰符是Static的话里面可以传入任何值包括null;

  • 调用方法:
    这里必须注意的是当操作的对象用private修饰的时候需要用method.setAccessible(true)来设置可以访问到.然后调用method.invoke(Object obj,参数),这个Object的对象必须是该类的对象.不是所谓的类对象.


四.Android能用到的地方

  • 修改TabLayout的下划线的长度.
    对于TabLayout的使用这里就不必多说了,系统只提供了修改下划线的高度和颜色的方法,并没有修改长度的方法.这里就要用到反射区获取TabLayout内部控制长度的方法.这里只能通过设置每个Tab的Margin来控制下划线的宽度,有可能出现Tab的文字被挤压的情况,只能将就使用了.代码如下:
    Class<? extends TabLayout> tabClass = tabLayout.getClass();
         try {
             Field mTabStrip = tabClass.getDeclaredField("mTabStrip");
             mTabStrip.setAccessible(true);
            LinearLayout linearLayout = (LinearLayout) mTabStrip.get(tabLayout);
             for (int i = 0; i < linearLayout.getChildCount(); i++) {
                 View child = linearLayout.getChildAt(i);
                 child.setPadding(0,0,0,0);
                 LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) child.getLayoutParams();
                // layoutParams.width = 300;
                 layoutParams.leftMargin = 150;
                 layoutParams.rightMargin = 150;
                 child.setLayoutParams(layoutParams);
                 child.invalidate();
             }
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         }复制代码
  • 控制Toast的显示时间.
    Toast内部类TN的设置显示时间的代码:

    mParams.hideTimeoutMilliseconds = mDuration ==
        Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
                     ...
        /**
          * schedule handleHide into the right thread
          */
         @Override
         public void hide() {
             if (localLOGV) Log.v(TAG, "HIDE: " + this);
             mHandler.obtainMessage(HIDE).sendToTarget();
         }复制代码

    这里系统自带的Toast只给了我们两个时间的选择SHORT_DURATION_TIMEOUT和LONG_DURATION_TIMEOUT其他的我们没法改变.还好系统提供了hide方法不过在外面我们是访问不到,这里我们也可以用到反射,大部分的操作都是Toast的内部类TN来完成的.首先获取到Toast的class对象,Toast内部含有内部类的字段(final TN mTN),这样我们可以获取到内部类的对象,然后再通过内部类的Class对象来获取内部类里面的hide()方法.代码如下:

    try{
                     Class<Toast> toastClass = Toast.class;
                     Field mTN = toastClass.getDeclaredField("mTN");
                     //获取修饰符类型
                     toastClass.getModifiers();
                     mTN.setAccessible(true);
                     Object o = mTN.get(toast);
                     Class<?> aClass = o.getClass();
                     Method hide = aClass.getDeclaredMethod("hide");
                     hide.setAccessible(true);
                     hide.invoke(o);
                 } catch (NoSuchFieldException e) {
                     e.printStackTrace();
                 } catch (IllegalAccessException e) {
                     e.printStackTrace();
                 } catch (InvocationTargetException e) {
                     e.printStackTrace();
                 } catch (NoSuchMethodException e) {
                     e.printStackTrace();
                 }复制代码

    五.结束语

    反射对我们来说还是挺重要的,我们不需要多么的精通只需要在使用的时候不会那么陌生.对于有java基础的同学学起来还是比较容易的.

    欢迎大家的观看并提出宝贵的意见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java反射机制是一种能够在运行时检查和操作类、接口、方法以及属性的能力。通过反射,我们可以动态地获取类的信息,包括类的方法、构造方法和成员变量等。同时,我们还可以通过反射来创建类的实例、调用类的方法、设置和获取对象的属性值等操作。反射机制为我们提供了一种灵活、动态的方式来操作和使用Java类,使得我们可以在运行时根据需要动态地加载和使用类。通过反射,我们可以实现一些需要在编译时无法确定具体类名或方法名的操作,例如通过字符串获取Class、Method或Field等。然而,反射也存在一些性能问题,由于需要动态解析和匹配,导致性能开销较大。另外,每次反射调用都会引发Java安全机制进行额外的安全性验证,进一步降低性能。反射代码也会影响JVM的运行时优化。总之,通过Java反射机制,我们可以在运行时动态地获取和操作类的信息,提供了一种灵活、动态的方式来使用Java类。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Android开发你需要掌握的java反射机制原理](https://blog.csdn.net/u012514113/article/details/127443659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值