反射库提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序。
在程序运行期间,Java运行时系统为所有的对象维护一个被称作运行时的类型标识。这个信息追踪着每个对象所属的类。而此时,可以通过专门的类访问这些信息,保存这些信息的类称为Class。换句话说,在程序运行期间,我们在代码定义的每一个类都会对应一个Class对象,该对象保存了这个类的所有信息,其中包括类名、父类、实现的接口、属性、方法、构造方法等。
需要注意,一个Class对象实际上表示的是一种类型,而这个类型未必一定是累,也可以是int等原始类型。
获取Class对象有三种方式:
Class c = Class.forName("java.util.List");
Class c = Random.class
Random r = new Random(); Class c = r.getClass();
2.1 Class中常用API
上边我们知道Class对象保存的是java类运行时信息,因此Class中的API就是获取、修改java类的运行时信息
//=================Class对象中的方法====================== //获取类名(全路径类名) public String getName() //获取父类 public native Class<? super T> getSuperclass(); //获取实现的接口 public Class<?>[] getInterfaces() //判断类型是否为原始类型:java.lang.Boolean#TYPE,java.lang.Character#TYPE,java.lang.Byte#TYPE,java.lang.Short#TYPE,java.lang.Integer#TYPE,java.lang.Long#TYPE,java.lang.Float#TYPE,java.lang.Double#TYPE,java.lang.Void#TYPE public native boolean isPrimitive();
//=================Class对象中的方法====================== //根据字段名获取字段 public Field getField(String name) //获取类中所有共有字段,包括父类 public Field[] getFields() throws SecurityException //获取本类中所有字段 public Field[] getDeclaredFields() throws SecurityException //=================Field对象中的方法====================== //获取字段类型 public Class<?> getType() //获取字段名称 public String getName() //获取某个对象中某个字段的值(obj为拥有字段的某个对象) public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException //给某个对象的某个字段设置值 public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException
//=================Class对象中的方法====================== //调用默认构造函数创建创建对象 public T newInstance() throws InstantiationException, IllegalAccessException //根据参数获取构造函数 public Constructor<T> getConstructor(Class<?>... parameterTypes) //获取类中所有的共有构造器 public Constructor<?>[] getConstructors() throws SecurityException //获取本类中所有构造器(包括私有构造函数) public Constructor<?>[] getDeclaredConstructors() throws SecurityException //=================Constructor对象中的方法====================== //调用构造函数创建对象 public T newInstance(Object ... initargs)
//=================Class对象中的方法====================== //根据方法名称获取方法对象 public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException //获取类中所有共有方法(包括父类中的) public Method[] getMethods() throws SecurityException //获取类中所有方法(包括私有成员) public Method[] getDeclaredMethods() throws SecurityException //=================Method对象中的方法====================== //获取方法名 public String getName() //获取方法返回类型 public Class<?> getReturnType() //获取参数 public Parameter[] getParameters() //调用方法 public Object invoke(Object obj, Object... args)
//获取方法、类、字段修饰符整数 public int getModifiers() //转换String Modifier.toString(modifiers)//注:int modifiers = med.getModifiers(); //设置私有成员的反射访问权限 AccessibleObject.setAccessible(declaredFields,true);//注:Field[] declaredFields = objClass.getDeclaredFields(); public void setAccessible(boolean flag)
2.2 反射中关于数组操作的API
//判断是否是数组:Class类中 public native boolean isArray(); //获取数组元素的类型:Class类中 public native Class<?> getComponentType(); //创建数组 Array.newInstancenewInstance(Class<?> componentType, int length) //获取数组长度 public static native int getLength(Object array) throws IllegalArgumentException;
上面介绍了反射的基本API,其实除了上述的这些常用的API,反射中关于注解的API也很常用。
反射机制可以用来:
上述四个作用我们分别用四个案例说明。
public class Reflection01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); Class<Double> doubleClass = Double.class; //获取类修饰符 int modifiers = doubleClass.getModifiers(); String cd = Modifier.toString(modifiers); sb.append(cd + " "); //获取类名 String className = doubleClass.getName(); sb.append(className + " "); //获取继承的类 Class<? super Double> superclass = doubleClass.getSuperclass(); if (superclass!=null) { sb.append("extend "+superclass.getName()+" "); } Class<?>[] interfaces = doubleClass.getInterfaces(); //获取实现的接口 if (interfaces.length>0){ sb.append("implements "); for (Class<?> anInterface : interfaces) { sb.append(anInterface.getName()+" "); } } sb.append("\n{"); System.out.print(sb); printConstructors(doubleClass); System.out.println(); printFields(doubleClass); System.out.println(); printMethods(doubleClass); System.out.println("}"); } //打印构造方法 public static void printConstructors(Class c) { //获取类中所有的构造方法(私有的和公有的) Constructor[] constructor = c.getDeclaredConstructors(); for (Constructor cons : constructor) { StringBuffer sb = new StringBuffer(); sb.append("\t"); //获取修饰符 int modifiers = cons.getModifiers(); String d = Modifier.toString(modifiers); sb.append(d+" "); //获取参数方法名 sb.append(cons.getName()+"("); //获取参数 Parameter[] parameters = cons.getParameters(); if (parameters.length>0){ for (int i = 0; i < parameters.length; i++) { Class<?> type = parameters[i].getType(); String cName = type.getName(); sb.append(cName); if (i<parameters.length-1){ sb.append(", "); } } } sb.append(");"); System.out.println(sb); } } //打印属性 public static void printMethods(Class c) { //获取类中的共有方法(包括父类中的共有方法) Method[] methods = c.getMethods(); for (Method med : methods) { StringBuffer sb = new StringBuffer(); sb.append("\t"); //获取修饰符 int modifiers = med.getModifiers(); String d = Modifier.toString(modifiers); sb.append(d+" "); //获取返回类型 Class<?> returnType = med.getReturnType(); sb.append(returnType.getName()+" "); //获取参数方法名 sb.append(med.getName()+"("); //获取参数 Parameter[] parameters = med.getParameters(); if (parameters.length>0){ for (int i = 0; i < parameters.length; i++) { Class<?> type = parameters[i].getType(); String cName = type.getName(); sb.append(cName); if (i<parameters.length-1){ sb.append(", "); } } } sb.append(");"); System.out.println(sb); } } //打印普通方法 public static void printFields(Class c) { Field[] fields = c.getFields(); for (Field field : fields) { StringBuffer sb = new StringBuffer("\t"); //获取修饰符 int modifiers = field.getModifiers(); String d = Modifier.toString(modifiers); sb.append(d+" "); //获取字段类型 Class<?> type = field.getType(); sb.append(type.getName()+" "); //获取字段名 sb.append(field.getName()+";"); System.out.println(sb); } //获取父类中共有方法 Class superclass = c.getSuperclass(); if (superclass!=null){ printFields(superclass); } } }
输出:========>
public final java.lang.Double extend java.lang.Number implements java.lang.Comparable { public java.lang.Double(double); public java.lang.Double(java.lang.String); public static final double POSITIVE_INFINITY; public static final double NEGATIVE_INFINITY; public static final double NaN; public static final double MAX_VALUE; public static final double MIN_NORMAL; public static final double MIN_VALUE; public static final int MAX_EXPONENT; public static final int MIN_EXPONENT; public static final int SIZE; public static final int BYTES; public static final java.lang.Class TYPE; public boolean equals(java.lang.Object); public static java.lang.String toString(double); public java.lang.String toString(); public int hashCode(); public static int hashCode(double); public static double min(double, double); public static double max(double, double); public static native long doubleToRawLongBits(double); public static long doubleToLongBits(double); public static native double longBitsToDouble(long); public volatile int compareTo(java.lang.Object); public int compareTo(java.lang.Double); public byte byteValue(); public short shortValue(); public int intValue(); public long longValue(); public float floatValue(); public double doubleValue(); public static java.lang.Double valueOf(java.lang.String); public static java.lang.Double valueOf(double); public static java.lang.String toHexString(double); public static int compare(double, double); public static boolean isNaN(double); public boolean isNaN(); public static boolean isInfinite(double); public boolean isInfinite(); public static boolean isFinite(double); public static double sum(double, double); public static double parseDouble(java.lang.String); public final void wait(long, int); public final native void wait(long); public final void wait(); public final native java.lang.Class getClass(); public final native void notify(); public final native void notifyAll(); }
public class Reflection02 { public static void main(String[] args) throws IllegalAccessException { List<Integer> list = new ArrayList<>(); list.add(1); list.add(11); list.add(111); System.out.println(new Reflection02().toString(list)); } private static List<Object> visited = new ArrayList<>(); public String toString(Object obj) throws IllegalAccessException { if (obj==null) return null; if (visited.contains(obj)) return "..."; visited.add(obj); Class<?> objClass = obj.getClass(); if (objClass.isArray()){ //获取数组类型 StringBuffer sb = new StringBuffer(); String s = objClass.getComponentType() + "[]{"; sb.append(s); //遍历数组元素 for (int i = 0; i < Array.getLength(obj); i++) { if (i>0){ sb.append(","); } Object val = Array.get(obj, i); if (objClass.getComponentType().isPrimitive()) sb.append(val); else sb.append(toString(val)); } sb.append("}"); return sb.toString(); } String className = objClass.getName(); StringBuffer sb = new StringBuffer(className); do { sb.append("["); Field[] declaredFields = objClass.getDeclaredFields(); AccessibleObject.setAccessible(declaredFields,true); for (Field field : declaredFields) { if (!Modifier.isStatic(field.getModifiers())){ if (!sb.toString().endsWith("[")){ sb.append(","); } sb.append(field.getName()+"="); Object val = field.get(obj); Class<?> fieldType = field.getType(); if (fieldType.isPrimitive()){ sb.append(val); }else { sb.append(toString(val)); } } } sb.append("]"); objClass = objClass.getSuperclass(); }while (objClass!=null); return sb.toString(); } }
输出:==========>
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=11][][],java.lang.Integer[value=111][][],null,null,null,null,null,null,null},size=3][modCount=3][][]
public class Reflection03 { public static void main(String[] args) { int[] arr = {1,1,11,22,12,21,2}; int[] newArr = (int[]) new Reflection03().copyArray(arr, 10); System.out.println(newArr.length); System.out.println(Arrays.toString(arr)); } /** * 复制数组到指定长度的新数组 * @param obj * @param length * @return */ public Object copyArray(Object obj,int length){ Class<?> objClass = obj.getClass(); if(!objClass.isArray()) return null; Class<?> componentType = objClass.getComponentType(); int objLength = Array.getLength(obj); Object arr = Array.newInstance(componentType, length); System.arraycopy(obj,0,arr,0,Math.min(objLength,length)); return arr; } }
输出:=============>
10 [1, 1, 11, 22, 12, 21, 2]
public class Reflection04 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method sqrt = Math.class.getMethod("sqrt", double.class); Object val = sqrt.invoke(null, 36); System.out.println(val); } }
输出:====================> 6.0
参考:《Java核心卷》卷1 ,5.7反射