- Class 类
- 利用反射分析类
- 在运行时使用反射分析对象
- 使用反射编写泛型数组代码
- 方法指针
能够分析类能力的程序称为反射(reflective). Java 提供了丰富且精心设计的工具集(reflection library).
Class 类在程序运行期间,Java 运行时系统始终为所有的对象维护着一个运行时的类型标识,这个信息保存着每个对象所属的类足迹.
获取 Class 实例.
// 1. 通过实例获得.Employee e;Class cl = e.getClass();// 2. 通过类名获得.String className = "java.util.Date";Class cl = Class.forName(className); // need try...catch// 3. 通过类获得.Class cl = Date.classClass cl = int.class
虚拟机为每个类型管理一个Class对象.
if (e.getClass = Employee.class) ...
通过 Class 创建实例.
e.getClass().newInstance(); // 需要有无参构造器Date.getClass().newInstance();Class.forName("xxx").newInstance();
在
java.lang.reflect
包中的三个核心类: Field、Method、Constructor.
使用反射分析类
package corejava.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Scanner;/** * Created by guolong.fan on 15/4/24. */public class ReflectionTest { public static void main(String[] args) { String name; if (args.length > 0) name = args[0]; else { Scanner in = new Scanner(System.in); System.out.PRintln("Enter class name(e.g. java.util.Date):"); name = in.next(); } try { // print class name and superclass name(if != Object) Class cl = Class.forName(name); Class supercl = cl.getSuperclass(); String modifiers = Modifier.toString(cl.getModifiers()); if (modifiers.length() > 0) System.out.print(modifiers + " "); System.out.print("class " + name); if (supercl != null && supercl != Object.class) { System.out.print(" extends " + supercl.getName()); } System.out.println(" {"); printConstructors(cl); System.out.println(); printMethods(cl); System.out.println(); printFields(cl); System.out.println("}"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static void printConstructors(Class cl) { Constructor[] constructors = cl.getDeclaredConstructors(); for (Constructor c : constructors) { String name = c.getName(); System.out.print("/t"); String modifiers = Modifier.toString(c.getModifiers()); if (modifiers.length() > 0) System.out.print(modifiers + " "); System.out.print(name + "("); Class[] paramTypes = c.getParameterTypes(); for (int j = 0; j < paramTypes.length; ++j) { if (j > 0) System.out.print(", "); System.out.print(paramTypes[j].getName()); } System.out.print(")"); Class[] expTypes = c.getExceptionTypes(); if (expTypes.length > 0) System.out.print(" throws "); for (int j = 0; j < expTypes.length; ++j) { if (j > 0) System.out.print(", "); System.out.print(expTypes[j].getName()); } System.out.println(";"); } } private static void printMethods(Class cl) { Method[] methods = cl.getDeclaredMethods(); for (Method m : methods) { String name = cl.getName(); Class refType = m.getReturnType(); System.out.print("/t"); String modifiers = Modifier.toString(m.getModifiers()); if (modifiers.length() > 0) System.out.print(modifiers + " "); System.out.print(refType.getName() + " "); System.out.print(name + "("); Class[] paramTypes = m.getParameterTypes(); for (int j = 0; j < paramTypes.length; ++j) { if (j > 0) System.out.print(", "); System.out.print(paramTypes[j].getName()); } System.out.print(")"); Class[] expTypes = m.getExceptionTypes(); if (expTypes.length > 0) System.out.print(" throws "); for (int j = 0; j < expTypes.length; ++j) { if (j > 0) System.out.print(", "); System.out.print(expTypes[j].getName()); } System.out.println(";"); } } private static void printFields(Class cl) { Field[] fields = cl.getDeclaredFields(); for (Field f : fields) { String name = f.getName(); Class type = f.getType(); String modifiers = Modifier.toString(f.getModifiers()); System.out.print("/t"); if (modifiers.length() > 0) System.out.print(modifiers + " "); System.out.println(type.getName() + " " + name + ";"); } }}
实现通用的toString
.
package corejava.reflection;import java.lang.reflect.accessibleObject;import java.lang.reflect.Array;import java.lang.reflect.Field;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.List;/** * Created by guolong.fan on 15/4/24. */public class ObjectAnalyzer { /** * Converts an object to a string representation that lists all fields. * @param obj an object * @return a string with the obejct's class name and all fields name and * values */ public String toString(Object obj) { if (obj == null) return "null"; if (visited.contains(obj)) return "..."; visited.add(obj); Class cl = obj.getClass(); if (cl == String.class) return (String)obj; if (cl.isArray()) { String r = cl.getComponentType() + "[]{"; for (int i = 0; i < Array.getLength(obj); ++i) { if (i > 0) r += ","; Object val = Array.get(obj, i); if (cl.getComponentType().isPrimitive()) r += val; else r += toString(val); } return r + "}"; } String r = cl.getName(); // inspect the fields of this class and all superclasses do { r += "["; Field[] fields = cl.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); for (Field f : fields) { if (!Modifier.isStatic(f.getModifiers())) { if (!r.endsWith("[")) r += ","; r += f.getName() + "="; try { Class t = f.getType(); Object val = f.get(obj); if (t.isPrimitive()) r += val; else r += toString(val); } catch (Exception e) { e.printStackTrace(); } } } r += "]"; cl = cl.getSuperclass(); } while (cl != null); return r; } private List<Object> visited = new ArrayList<Object>(); public static void main(String[] args) { ArrayList<Integer> squares = new ArrayList<Integer>(); for (int i = 0; i < 5; ++i) { squares.add(i * i); } System.out.println(new ObjectAnalyzer().toString(squares)); System.out.println(squares); }}
package corejava.reflection;import java.lang.reflect.Array;/** * Created by guolong.fan on 15/4/24. */public class ArrayGrowTest { public static void main(String[] args) { int[] a = { 1, 2, 3 }; a = (int[])goodArrayGrow(a); String[] b = { "Tom", "Dick", "Harry" }; b = (String[]) goodArrayGrow(b); // Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; // at corejava.reflection.ArrayGrowTest.main(ArrayGrowTest.java:10) System.out.println("The following call will generate an exception."); b = (String[])badArrayGrow(b); // 要理解这些,需要把泛型数组看成一种类型。Integer[] 和 Object[] 不是一种类型!!! // 有自己的 Class 对象!!! Integer[] intArr = new Integer[10]; Object[] objArr = intArr; // OK // Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer; // at corejava.reflection.ArrayGrowTest.main(ArrayGrowTest.java:20) Object[] objArr2 = new Object[10]; Integer[] intArr2 = (Integer[])objArr2; // Exception } /** * This method attempts to grow an array by alocating a new array and copying all elements. * @param a the array to grow * @return a larger array that contains all elements of a. However, the returned array has * type Object[], not the same type as a. */ static Object[] badArrayGrow(Object[] a) { int newLength = a.length * 11 / 10 + 10; Object[] newArray = new Object[newLength]; System.arraycopy(a, 0, newArray, 0, a.length); return newArray; // newArray is Object[], not the same type as a. } /** * This method grows an array by allocating a new array of the same type and * copying all elements. * @param a the array to grow. This can be an object array or a primitive * type array * @return a larger array that contains all elements of a. */ static Object goodArrayGrow(Object a) { if (a == null) return null; Class cl = a.getClass(); if (!cl.isArray()) return null; Class componentType = cl.getComponentType(); int length = Array.getLength(a); // 获取a的类型 int newLength = length * 11 / 10 + 10; Object newArray = Array.newInstance(componentType, newLength); // newArray is the same type as a!! System.arraycopy(a, 0, newArray, 0, length); return newArray; }}
Java 没有提供方法指针,但是利用反射可以实现方法指针,但是从设计角度来说,方法指针会来带隐患. interface 是更好的解决方案.
Method m1 = Employee.class.getMethod("getName");Method m2 = Employee.class.getMethod("raiseSalary", double.class);Employee e = new Employee();m1.invoke(e);m2.invoke(e, 1.0);
示例:
package corejava.reflection;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;/** * Created by guolong.fan on 15/4/24. */public class MethodPointerTest { public static void main(String[] args) throws NoSuchMethodException { Method square = MethodPointerTest.class.getMethod("squre", double.class); printTable(1, 10, 10, square); } public static double squre(double x) { return x * x; } private static void printTable(double from, double to, int n, Method f) { double dx = (to - from) / (n - 1); for (double x = from; x <= to; x += dx) { try { double y = (Double)f.invoke(null, x); System.out.printf("%10.4f | %10.4f/n", x, y); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }}
新闻热点
疑难解答