首页 > 学院 > 开发设计 > 正文

Core Java笔记 3.反射

2019-11-15 00:00:07
字体:
来源:转载
供稿:网友
Core java笔记 3.反射本章重点:
  • 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();            }        }    }}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表