TIII-Android技术篇之反射

mac2022-06-30  109

对于一个类来说,最重要的是什么?

构造+属性+方法+访问权限
待测试的类
/** * 作者:张风捷特烈 * 时间:2018/5/6:10:40 * 邮箱:1981462002@qq.com * 说明:反射测试类 */ public class Person { private int age; private String name; private boolean isMan; public String address="beijing"; public Person() { System.out.println("空参构造执行..."); } public Person( String name, int age,boolean isMan) { this.age = age; this.name = name; this.isMan = isMan; System.out.println("三参构造执行..."); } public void publicShow() { System.out.println("I am " + name + ",I " + age + "years"); } public static void staticShow() { System.out.println("staticShow"); } private void privateShow() { System.out.println("I am " + name + ",I " + age + "years"); } public void paramShow(String str,int num) { System.out.println("I am " + str + ",I " + num + "years"); } }

一、拿到Class对象

Class对象是什么?

Class是一个类,而且它只有一个私有的构造函数,说明它不能通过new来获取对象,构造函数传入一个ClassLoader。 每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象, 通过该Class对象就可以访问到JVM中的这个类,就可以获取某类的一切 private Class(ClassLoader loader) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; }
1.对象.getClass()获取Class对象

前提:已存在对象,未知该类全貌,可以使用此方法获取Class对象来探测该类

Object类中有一个native方法获取Class public final native Class<?> getClass(); public static void getClass_1() { Person person = new Person(); Class<? extends Person> personClass = person.getClass(); }
2.类名.class获取Class对象

前提:需要已知类名

public static void getClass_2() { Class<Person> personClass = Person.class; }
3.通过指定字符串:获取Class对象

前提:需已知全类名

public static void getClass_3() { try { Class<?> person = Class.forName("top.toly.bean.Person"); System.out.println(person); } catch (ClassNotFoundException e) { e.printStackTrace(); } }

二、通过反射构造对象

1.获取无参构造实例化对象:clazz.newInstance()
/** * 通过反射建无参实例 */ public static void createInstance() { //早期:new 的时候,先根据类名寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 // 再创建该字节码文件对相应的Person对象 try { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); Object instance = clazz.newInstance(); System.out.println(instance instanceof Person);//true } catch (Exception e) { e.printStackTrace(); }
2.通过反射建有参实例:clazz.getConstructor
/** * 通过反射建有参实例 */ private static void createInstance_2() { try { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); System.out.println(instance); //Person{age=24, name='捷特', isMan=true, address='beijing'} } catch (Exception e) { e.printStackTrace(); } }
补充:XXXDeclaredXXX都是只获取本类,不包括父类
// 获得该类所有的构造器,不包括其父类的构造器 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) // 获得该类所以public构造器,包括父类 public Constructor<T> getConstructor(Class<?>... parameterTypes)

三、通过反射获取字段

1.获取公共字段:clazz.getField
/** * 获取公共字段 */ public static void getPublicField() throws Exception { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); Field address = clazz.getField("address");//获取公有字段 Object o = address.get(clazz.newInstance()); System.out.println(o);//beijing }
2.获取私有字段:
/** * 获取私有字段 */ public static void getPrivateField() throws Exception { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); //可以获取所有类型字段 Field name = clazz.getDeclaredField("age"); //想要访问私有,需要将可获取置为true name.setAccessible(true); //设置私有成员值 name.setInt(instance,30); //获取私有成员值 Object o = name.get(instance); System.out.println(o);//30 }

四、调用方法:

1.获取公共方法:getMethods()
/** * 获取公共方法 */ public static void getPublicMethod() throws Exception { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); //创建实例 Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); Method[] methods = clazz.getMethods();//只能获取公有方法,包括父类 for (Method m : methods) { System.out.println(m); } //获取公共无参 Method publicShow = clazz.getMethod("publicShow", null); //调用函数:invoke publicShow.invoke(instance, null); //获取公共有参 Method paramShow = clazz.getMethod("paramShow", String.class, int.class); paramShow.invoke(instance, "龙少", 24); }

clazz.getDeclaredMethod:获取指定名称和参数类型的本类中声明(访问权限不限)的方法 clazz.getDeclaredMethods(): 获取该类所有的方法,不包括父类 clazz.getMethod:获取当前类及所有继承的父类的public修饰的方法。仅包括public clazz.getMethods();获取该类所有的public方法,包括父类的

2.获取私有方法:getDeclaredMethods()
/** * 获取私有方法 */ public static void getPrivateMethod() throws Exception { String className = "top.toly.bean.Person"; // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。 Class<?> clazz = Class.forName(className); Method[] declaredMethods = clazz.getDeclaredMethods();//获取该类中的所有方法 //创建实例 Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); for (Method m : declaredMethods) { System.out.println(m); } Method privateShow = clazz.getDeclaredMethod("privateShow", null); privateShow.setAccessible(true); privateShow.invoke(instance,null); }

反射差不多也就这些,理论并不难,学以致用才是关键


后记、

1.声明:

[1]本文由张风捷特烈原创,转载请注明 [2]欢迎广大编程爱好者共同交流 [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 [4]你的喜欢与支持将是我最大的动力

2.连接传送门:

更多安卓技术欢迎访问:安卓技术栈 我的github地址:欢迎star 简书首发,腾讯云+社区同步更新 张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

3.联系我

QQ:1981462002 邮箱:1981462002@qq.com 微信:zdl1994328

4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
公众号.jpg

转载于:https://www.cnblogs.com/toly-top/p/9781884.html

最新回复(0)