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,非静态方法,传对象obj2 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、调用一个隐藏的类或一个类的私有方法或私有属性。
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 }