Java 反射学习
Android中有些方法是不能调用的,因为没有对外提供使用权限,这时候可以用反射来实现
一.场景
- try {
- // 获取系统电话管理的服务
- Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
- IBinder binder = (IBinder)method.invoke(null, new Object[]{TELEPHONY_SERVICE});
- iTelephony = ITelephony.Stub.asInterface(binder);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
}
可以改为
- //1.获取类
- Class clazz =Class.forName("android.os.ServiceManager");
- //2.通过类获取方法
- Method method =clazz.getMethod("getService", String.class);
- //3.调用获取的方法,取得返回值(method的作用对象为空,可以看出getService在源码中是一个静态方法)
- IBinder binder =(IBinder)method.invoke(null, new Object[]{TELEPHONY_SERVICE});
- iTelephony = ITelephony.Stub.asInterface(binder);
二.什么是反射?
一句话:反射就是把java类中的各种成分映射成为相应的java类
Java类编译后变成了.class 二进制字节文件,将这些加载jvm中二进制字节文件映射成为对应的类就是反射
三、为什么要用反射?
1.实现框架功能 :通过配置文件调用类(Properties类)
2.Android中某些系统类没有对外提供使用权限,比如文章开头中的场景提到的代码,我们无法通过类名直接实例化出对象,然后拿着对象.方法(),这时候也可以使用反射
3.1反射的使用代码案例
- /首先根据包名 获取对应类的Class实例
- Class clazz = Class.forName("com.vincent.java.entity.Person");
- /**
- * 0.通过无参构造函数实例化对象
- */
- Person p =(Person)clazz.newInstance();
- //p.sayHello();
- /**
- *
- *
- * 1.通过Constructor实例实例化对象
- *
- * 有参构造函数实例化对象()---getConstructor(参数1类型.class,参数2类型.class)
- */
- Constructor con =clazz.getConstructor(int.class,String.class);
- Person p2 = (Person) con.newInstance(12,"dxx");
- System.out.println(p2.toString());
- /**
- * 2.使用Field获取成员变量
- *
- * class.getFeild("变量名字");
- * fild.set(作用对象,变量修的新值);
- */
- Field x = clazz.getField("name");
- x.set(p2, "dongxiangxiagn");
- System.out.println(p2.toString());
- /**
- * 3.调用方法
- */
- //- 通过getMethod(方法名字,参数类型.class)获得方法对应的Method实例
- //- 通过method的invoke(方法作用对象,new Object[]{参数值1,参数值2...})来调用方法
- //调用无参方法 sayHello();
- Method method_void =clazz.getMethod("sayHello", null);
- method_void.invoke(clazz.newInstance(), null);
- //调用有参方法 sayHello(String str);
- Method method =clazz.getMethod("sayHello", String.class);
- method.invoke(clazz.newInstance(), new Object[]{"vincent"});
- //调用静态方法 sayStaticHello();
- //静态方法invoke时候的最用对象处,传入null即可
- Method method_static = clazz.getMethod("sayStaticHello", null);
- method_static.invoke(null, null);
- //调用带返回值的多参方法 float subXAndY(float x,float y);
- Method method_sub = clazz.getMethod("subXAndY", float.class,float.class);
- Float result = (Float) method_sub.invoke(null, new Object[]{2.0f,100.0f});
- System.out.print("The sub result is :"+result);
- /**
- * 4.调用String的char方法
- */
- String charStr = "abc";
- Class class_Char = Class.forName("java.lang.String");
- Method mehtod_charAt = class_Char.getMethod("charAt", int.class);
- System.out.println(mehtod_charAt.invoke(charStr, 2));
3.2关于数组反射的使用案例
- //获取Class类对象
- Class clazz = obj.getClass();
- if (clazz.isArray()) {// 判断是否是数组
- System.out.println("YES,传入的对象是数组,开始打印");
- /**
- * Array 类提供了动态创建和访问 Java 数组的方法。
- *
- * Array 允许在执行 get 或 set 操作期间进行扩展转换
- *
- */
- int length = Array.getLength(obj);
- for (int i = 0; i < length; i++) {
- System.out.println(Array.get(obj, i));
- }
- } else {
- System.out.println("NO,传入的对象不是是数组,开始打印");
- System.out.println(obj);
- }
四.关于Class的实验
通过 1.对象.getClass( )方法 2.类名.class 3.Class.forName(包名.类名)
三种方法得出的Class对象都是同一个对象