Android 中java反射应用(三)——应用场景及总结

本文通过游戏配置文件选择渲染器实例和调用隐藏类两个场景,介绍了Java反射机制的应用,包括运行时确定对象及方法和调用隐藏类或私有方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


反射应用场景


第一种:
运行时确认对象以及方法


1、下面举个简单的例子来说下反射的运用场景:

  假如一款游戏有一个配置文件,配置文件里有个renderType设置了游戏启动时调用哪个RenderHandler来渲染游戏,

  (RenderHandler:一个接口,有一个render方法,HighRenderHandler、LowRenderHandler、MiddleRenderHandler等一共10个实现类)

  那么游戏启动时必须获得一个RenderHandler来渲染游戏,现在有两种方式,一种是使用switch判断

复制代码
 1 //首先获得配置文件里的renderType
 2 switch(renderType){
 3      case "low":renderHandler=new LowRenderHandler();
 4      case "high":renderHandler=new HighRenderHandler();
 5      case "middle":renderHandler=new MiddleRenderHandler();
 6      case "a":renderHandler=new ARenderHandler();
 7      case "b":renderHandler=new BRenderHandler();
 8      case "c":renderHandler=new CRenderHandler();
 9      case "d":renderHandler=new DRenderHandler();
10      case "e":renderHandler=new ERenderHandler();
11      case "f":renderHandler=new FRenderHandler();
12      case "g":renderHandler=new GRenderHandler();
13      default:renderHandler=new LowRenderHandler();
14  }
15  renderHandler.render();
复制代码

    

另一种是使用反射:



1 //首先从配置文件里获得renderType
 //这里直接强转为RendeHandler,是因为他是所有的handler的父类,且可以直接调用render()方法
//如没有共同父类,只能写成Class,且调方法时要getMethod,然后method.invoke(Object obj,Object... args) ,当用静态方法时obj传类class,非静态方法,传对象obj
2 RendeHandler renderHandler=(RendeHandler)Class.forName(rederType).newInstance();3 renderHandler.render();

 

2、switch用了14行代码,而反射只使用了2行代码,现实中可能见不到这么傻的例子,但是这确实有助于理解反射。


第二种:类是隐藏的,上层程序开发无法直接使用

Systemproperties类在android.os下,但这个类是隐藏的,上层程序开发无法直接使用,只能通过java反射来调用

public class SystemPropertiesInvoke {
    private static final String TAG = "SystemPropertiesInvoke";
    private static Method getLongMethod = null;
       
    public static long getLong(final String key, final long def) {
        try {
            if (getLongMethod == null) {
                getLongMethod = Class.forName("android.os.SystemProperties")
                        .getMethod("getLong", String.class, long.class);
            }
            
            return ((Long) getLongMethod.invoke(null, key, def)).longValue();
        } catch (Exception e) {
            Log.e(TAG, "Platform error: " + e.toString());
            return def;
        }
    }

}

 

补充几点:

1、反射获取到的私有属性设置可用:Field.setAccessible();

2、反射获取到的方法执行时的参数:

invoke(Object receiver, Object... args),当是静态方法时,传类class;当非静态,传对象object。
3、反射应用场景:a、运行时才知道要实例化哪一个类;b、调用一个隐藏的类或一个类的私有方法或私有属性。


1、Field.setAccessible()方法

 

java代码中,常常将一个类的成员变量置为private

 在类的外面获取此类的私有成员变量的value时,需要注意:

测试类:

复制代码
 1     public class AccessibleTest {  
 2       
 3         private int id;  
 4         private String name;  
 5       
 6         public AccessibleTest() {  
 7       
 8         }  
 9       
10         public int getId() {  
11             return id;  
12         }  
13       
14         public void setId(int id) {  
15             this.id = id;  
16         }  
17       
18         public String getName() {  
19             return name;  
20         }  
21       
22         public void setName(String name) {  
23             this.name = name;  
24         }  
25       
26     }  
复制代码

Main类:

复制代码
 1     public class Main {  
 2       
 3         public static void main(String[] args) throws Exception {  
 4             Class clazz = Class.forName("com.test.accessible.AccessibleTest");  
 5             AccessibleTest at = new AccessibleTest();  
 6             at.setId(1);  
 7             at.setName("AT");  
 8             for (Field f : clazz.getDeclaredFields()) {  
 9                 f.setAccessible(true);//AccessibleTest类中的成员变量为private,故必须进行此操作  
10                 System.out.println(f.get(at));//获取当前对象中当前Field的value  
11             }  
12       
13         }  
14       
15     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值