一、反射概述
在平常的开发中Java的反射技术很少被用到,一般我们都是使用公司封装或者开源框架。而反射技术已经被包含到底层框架了,因此我们很少接触到。但是有些框架的原理或者源码如果想读懂就必须要理解并会使用反射技术。例如:EventBus、BufferKnife、android的插件化等等都会用到。理解了反射技术能够帮助我们更快的理解相关框架,也可以增强我们开发人员的基本功。
Java中的反射能做到什么?
1.根据一个字符串的到一个类对象
2.获取一个类的所有的共有、私有方法或者属性(包括静态的)
3.可以对泛型进行反射
二、根据一个字符串得到Class
1package com.yw.reflectjavalib; 2 3 4/** 5 * 获取类对象的三种方式 6 */ 7public class ReflectDemoTest { 8 /** 9 * 程序的入口,main方法 10 * 11 * @param args 12 */ 13 public static void main(String[] args) { 14 LogUtil.e("根据一个字符串获取类全名"); 15 str2Class(); 16 LogUtil.e("使用Class.forName获取类全名"); 17 classForName(); 18 } 19 20 /** 21 * 根据一个字符串得到一个类 22 */ 23 public static void str2Class() { 24 String str = "hello world"; 25 Class classes = str.getClass(); 26 LogUtil.e(classes.getName());// 27 } 28 29 /** 30 * 使用ClassForName获取类 31 */ 32 public static void classForName() { 33 try { 34 Class str = Class.forName("java.lang.String"); 35 Class tv = Class.forName("com.yw.reflectjavalib.LogUtil"); 36 LogUtil.e(str.getName()); 37 LogUtil.e(tv.getName()); 38 //根据getSupperclass获取超类全名,由于LogUtil的超类是Object,所以Object会被打印 39 LogUtil.e(str.getSuperclass().getName()); 40 } catch (ClassNotFoundException e) { 41 e.printStackTrace(); 42 } 43 44 } 45 46 /** 47 * 根据类的class属性获取类对象 48 */ 49 public static void classAtb() { 50 Class c = String.class; 51 LogUtil.e(c.getName()); 52 LogUtil.e(c.getSuperclass().getName()); 53 } 54 55}
三、反射构造方法,并创建实例
1package com.yw.reflectjavalib; 2 3import java.lang.reflect.Constructor; 4import java.lang.reflect.Modifier; 5 6/** 7 * 获取类的成员 8 * 如:方法、属性、参数 9 * create by yangwei 10 * on 2020-02-07 14:48 11 */ 12public class ClassMemberDemo { 13 14 /** 15 * 程序的入口main方法 16 * 17 * @param args 18 */ 19 public static void main(String[] args) { 20 //获取类的构造函数 21 //获取类的所有构造函数 22 Book book = new Book(); 23 //获取book类对象 24 Class bookClass = book.getClass(); 25 //获取book类的所有的构造函数 26 Constructor[] constructors = bookClass.getDeclaredConstructors(); 27 //打印出构造函数名称、修饰符以及构造函数的参数 28 for (Constructor c : constructors) { 29 int mod = c.getModifiers();//获取构造函数的修饰符 30 LogUtil.e(Modifier.toString(mod) + ":" + c.getName()); 31 Class[] params = c.getParameterTypes();//获取构造函数的参数 32 StringBuffer sb = new StringBuffer(); 33 for (Class cs : params) { 34 sb.append(cs.getName()).append(","); 35 } 36 LogUtil.e(sb.toString()); 37 } 38 39 //获取book类的无惨构造函数 40 try { 41 Constructor noC = bookClass.getDeclaredConstructor(); 42 int mod = noC.getModifiers(); 43 LogUtil.e(Modifier.toString(mod) + ":" + noC.getName()); 44 } catch (NoSuchMethodException e) { 45 e.printStackTrace(); 46 } 47 //获取一个参数的构造函数 48 try { 49 Constructor oneC = bookClass.getDeclaredConstructor(String.class); 50 int mod = oneC.getModifiers(); 51 LogUtil.e(Modifier.toString(mod) + ":" + oneC.getName()); 52 } catch (NoSuchMethodException e) { 53 e.printStackTrace(); 54 } 55 //获取有两个参数的构造函数 56 try { 57 Constructor towC = bookClass.getDeclaredConstructor(String.class, String.class); 58 int mod = towC.getModifiers(); 59 LogUtil.e(Modifier.toString(mod) + ":" + towC.getName()); 60 } catch (NoSuchMethodException e) { 61 e.printStackTrace(); 62 } 63 64 //通过Class实例化一个对象 65 try { 66 Constructor constructor = bookClass.getDeclaredConstructor(); 67 Object object = constructor.newInstance(); 68 Book book1 = (Book) object; 69 book1.setBookName("《深入Java虚拟机》"); 70 LogUtil.e(book1.getBookName()); 71 } catch (Exception e) { 72 e.printStackTrace(); 73 } 74 //通过Class.forName实例化加载一个类,并实例化一个对象,并打印书本名称 75 try { 76 Class classBook = Class.forName("com.yw.reflectjavalib.Book"); 77 Constructor constructor = classBook.getDeclaredConstructor(String.class, String.class); 78 Object object = constructor.newInstance("《深入Java虚拟机》", "001"); 79 Book book2 = (Book) object; 80 LogUtil.e(book2.getBookName()); 81 } catch (Exception e) { 82 e.printStackTrace(); 83 } 84 85 86 } 87 88 89}
四、反射方法(包括静态)
1package com.yw.reflectjavalib; 2 3import java.lang.reflect.Constructor; 4import java.lang.reflect.Field; 5import java.lang.reflect.Method; 6 7/** 8 * java反射方法操作 9 * create by yangwei 10 * on 2020-02-07 16:12 11 */ 12public class ReflectMethodDemo { 13 /** 14 * 程序的入口main方法 15 * 16 * @param args 17 * @throws Exception 18 */ 19 public static void main(String[] args) throws Exception { 20 //获取Book类的私有方法getBookId并执行这个私有方法 21 Class bookClass = Book.class; 22 //创建实例 23 Constructor bookCon = bookClass.getDeclaredConstructor(); 24 Object object = bookCon.newInstance(); 25 //获取这个方法 26 Method method = bookClass.getDeclaredMethod("getBookId", new Class[]{}); 27 //执行这个方法 28 method.setAccessible(true); 29 method.invoke(object, new Object[]{}); 30 31 32 //使用Class.forName。执行类的静态私有方法 33 Class bookClass2 = Class.forName("com.yw.reflectjavalib.Book"); 34 Method method1 = bookClass2.getDeclaredMethod("write"); 35 method1.setAccessible(true); 36 method1.invoke(null);//静态方法属于类本身,所以这块执行jinvoke的时候不需要带任何参数 37 38 39 //获取book类的私有实例字段bookName并执行修改 40 Class bookClass3 = Book.class; 41 Constructor con3 = bookClass3.getDeclaredConstructor(); 42 Object obj3 = con3.newInstance(); 43 Field field = bookClass3.getDeclaredField("bookName"); 44 field.setAccessible(true); 45 field.set(obj3, "《设计模式》"); 46 Method method2 = bookClass3.getDeclaredMethod("getBookName"); 47 method2.setAccessible(true); 48 method2.invoke(obj3, new Object[]{}); 49 50 //后去book的私有静态字段并修改 51 Class bookClass4 = Book.class; 52 Constructor con4 = bookClass4.getDeclaredConstructor(); 53 Object obj4 = con4.newInstance(); 54 Field field1 = bookClass4.getDeclaredField("book"); 55 field1.setAccessible(true); 56 field1.set(obj4, "你真坏"); 57 Object objf = field1.get(null); 58 LogUtil.e(objf.toString()); 59 } 60 61 62}
五、反射属性
1package com.yw.reflectjavalib; 2 3import java.lang.reflect.Field; 4 5/** 6 * 对属性进行反射并操作属性 7 * create by yangwei 8 * on 2020-02-16 17:04 9 */ 10public class ReflectFiledDemo { 11 public static void main(String[] args) { 12// optionFiled(); 13 optionStaticFiled(); 14 } 15 16 /** 17 * 操作属性 18 */ 19 public static void optionFiled() { 20 try { 21 Class bookClass = Book.class; 22 //创建Book实例 23 Object bookObj = bookClass.newInstance(); 24 //获取book类的bookName属性 25 Field field = bookClass.getDeclaredField("bookName"); 26 field.setAccessible(true); 27 //获取Field中的值 28 String bookName = (String) field.get(bookObj); 29 System.out.println(bookName); 30 31 //设置Field的值 32 field.set(bookObj, "《大话数据结构》"); 33 //重新取出值 34 String bookName2 = (String) field.get(bookObj); 35 System.out.println(bookName2); 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 40 41 } 42 43 /** 44 * 操作静态属性 45 */ 46 public static void optionStaticFiled() { 47 try { 48 Class bookClass = Book.class; 49 Field field = bookClass.getDeclaredField("book"); 50 field.setAccessible(true); 51 //获取静态字段book的值 52 String bookName = (String)field.get(null); 53 System.out.println(bookName); 54 //设置静态属性book的值 55 field.set(null, "<深入Java虚拟机>"); 56 //重新取出值 57 String bookName2 = (String) field.get(null); 58 System.out.println(bookName2); 59 } catch (Exception e) { 60 e.printStackTrace(); 61 } 62 } 63}
六、获取基本数据类型类对象
1package com.yw.reflectjavalib; 2 3/** 4 * 基本数据类型获取类对象 5 * create by yangwei 6 * on 2020-02-07 14:42 7 */ 8public class BaseTypeDemo { 9 public static void main(String[] args) { 10 Class bool = Boolean.TYPE; 11 Class mByte = Byte.TYPE; 12 Class mInt = Integer.TYPE; 13 Class mShort = Short.TYPE; 14 Class mLong = Long.TYPE; 15 Class mFloat = Float.TYPE; 16 Class mDouble = Double.TYPE; 17 Class mChart = Character.TYPE; 18 Class mVoid = Void.TYPE; 19 LogUtil.e("boolean:" + bool.getName()); 20 LogUtil.e("byte:" + mByte.getName()); 21 LogUtil.e("int:" + mInt.getName()); 22 LogUtil.e("short:" + mShort.getName()); 23 LogUtil.e("long:" + mLong.getName()); 24 LogUtil.e("float:" + mFloat.getName()); 25 LogUtil.e("double:" + mDouble.getName()); 26 LogUtil.e("chart:" + mChart.getName()); 27 //我们常用的void也是有数据类型的,着点大家不要忽略了 28 LogUtil.e("void:" + mVoid.getName()); 29 30 31 } 32 33 34}
总结:说句实在话,Java的反射技术真心是晦涩难懂,初学者看着看着可能就懵逼了。为了方便操作在框架层面通常会把Java的反射技术封装成为一个类库,提供给开发者使用。
例如现成的:JOOR。下一节介绍手动封装反射类库(只有一个类),大家可以在做有反射项目的时候直接拿来使用。