20220210 Java 反射基础类

主要的相关类

  • java.lang.Class
  • java.lang.reflect.Method
  • java.lang.reflect.Field
  • java.lang.reflect.Modifier
  • java.lang.reflect.Constructor

Class 类

除了int等基本类型外,Java的其他类型全部都是class(包括interface)。

如何获取一个classClass实例?有三个方法:

  • 直接通过一个class的静态变量class获取:

    Class cls = String.class;
    
  • 如果我们有一个实例变量,可以通过该实例变量提供的getClass()方法获取:

    String s = "Hello";
    Class cls = s.getClass();
    
  • 如果知道一个class的完整类名,可以通过静态方法Class.forName()获取:

    Class cls = Class.forName("java.lang.String");
    

动态加载:JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载。

/**
 * Class 类
 */
public class ClassMain {
    public static void main(String[] args) {
        // printClassInfo("".getClass());
        // printClassInfo(Runnable.class);
        // printClassInfo(java.time.Month.class);
        // printClassInfo(String[].class);
        // printClassInfo(int.class);

        // getParentClassInfo();

        // getInterface();


        getInherit();
    }

    /**
     * 继承关系
     * 当我们判断一个实例是否是某个类型时,正常情况下,使用instanceof操作符
     * 如果是两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom():
     *
     *
     * 通过Class对象可以获取继承关系:
     * Class getSuperclass():获取父类类型;
     * Class[] getInterfaces():获取当前类实现的所有接口。
     * 通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。
     */
    private static void getInherit() {
        Object n = Integer.valueOf(123);
        boolean isDouble = n instanceof Double; // false
        boolean isInteger = n instanceof Integer; // true
        boolean isNumber = n instanceof Number; // true
        boolean isSerializable = n instanceof java.io.Serializable; // true


        // Integer i = ?
        Integer.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Integer
        // Number n = ?
        Number.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Number
        // Object o = ?
        Object.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Object
        // Integer i = ?
        Integer.class.isAssignableFrom(Number.class); // false,因为Number不能赋值给Integer
    }


    /**
     * 获取interface
     * 如果一个类没有实现任何interface,那么getInterfaces()返回空数组。
     */
    private static void getInterface() {
        Class s = Integer.class;
        Class[] is = s.getInterfaces();
        for (Class i : is) {
            System.out.println(i);
        }
        // interface java.lang.Comparable
    }

    /**
     * 获取父类的Class
     */
    private static void getParentClassInfo() {
        Class i = Integer.class;
        Class n = i.getSuperclass();
        System.out.println(n);  // class java.lang.Number
        Class o = n.getSuperclass();
        System.out.println(o);  // class java.lang.Object
        System.out.println(o.getSuperclass());  // null
    }


    static void printClassInfo(Class cls) {
        System.out.println("==============================");
        System.out.println("Class name: " + cls.getName());
        System.out.println("Canonical name: " + cls.getCanonicalName());
        System.out.println("Simple name: " + cls.getSimpleName());
        if (cls.getPackage() != null) {
            System.out.println("Package name: " + cls.getPackage().getName());
        }
        System.out.println("is interface: " + cls.isInterface());
        System.out.println("is enum: " + cls.isEnum());
        System.out.println("is array: " + cls.isArray());
        System.out.println("is primitive: " + cls.isPrimitive());
    }
}

访问字段 Field

public class FieldMain {
    public static void main(String[] args) throws Exception {
        getFieldTest();
        getFieldDetailTest();
    }

    /**
     * Field getField(name):根据字段名获取某个public的field(包括父类)
     * Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
     * Field[] getFields():获取所有public的field(包括父类)
     * Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
     */
    private static void getFieldTest() throws Exception {
        System.out.println("=================== getFieldTest ===================");
        Class stdClass = Student.class;

        System.out.println(Arrays.toString(stdClass.getFields()));  // score , name
        System.out.println(Arrays.toString(stdClass.getDeclaredFields()));  // score , grade
    }

    private static void getFieldDetailTest() throws Exception {
        System.out.println("=================== getFieldDetailTest ===================");
        Field f = String.class.getDeclaredField("value");
        Class<?> type = f.getType();
        int m = f.getModifiers();

        System.out.println(f);  // private final char[] java.lang.String.value
        System.out.println(f.toGenericString());
        System.out.println(f.getName());    //
        System.out.println(type.getCanonicalName()); // class [B 表示byte[]类型
        System.out.println(Modifier.isFinal(m)); // true
        System.out.println(Modifier.isPublic(m)); // false
        System.out.println(Modifier.isProtected(m)); // false
        System.out.println(Modifier.isPrivate(m)); // true
        System.out.println(Modifier.isStatic(m)); // false

        // 泛型相关
        Field f2 = GenericType.class.getDeclaredField("type");
        System.out.println(f2); // java.lang.Object reflection.FieldMain$GenericType.type
        System.out.println(f2.toGenericString());   // java.lang.Object reflection.FieldMain$GenericType.type

        Field f3 = GenericType.class.getDeclaredField("typeList");
        System.out.println(f3); // java.util.List reflection.FieldMain$GenericType.typeList
        System.out.println(f3.toGenericString());   // java.util.List<T> reflection.FieldMain$GenericType.typeList
    }

    class GenericType<T>{
        T type;
        List<T> typeList;
    }

    class Student extends Person {
        public int score;
        private int grade;
    }

    class Person {
        public String name;
        private String age;
    }

}
public class FieldValueMain {

    public static void main(String[] args) throws Exception {
        Person p = new Person("Xiao Ming");
        Class c = p.getClass();
        Field f = c.getDeclaredField("name");
        f.setAccessible(true); // private 时需要加上
        Object value = f.get(p);
        System.out.println(value); // "Xiao Ming"
        f.set(p, "Xiao Hong");
        System.out.println(p.getName()); // "Xiao Hong"
    }
}

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

调用方法 Method

/**
 * Method getMethod(name, Class...):获取某个public的Method(包括父类)
 * Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
 * Method[] getMethods():获取所有public的Method(包括父类)
 * Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
 */
public class MethodMain {
    public static void main(String[] args) throws Exception {
        // getMethod();
        // invokeMethod();
        // invokeStaticMethod();
        // invokePrivateMethod();
        invokeMultiMethod();
    }

    /**
     * 调用多态方法
     */
    private static void invokeMultiMethod() throws Exception {
        // 获取Person的hello方法:
        Method h = Person.class.getMethod("hello");
        // 对Student实例调用hello方法:
        h.invoke(new Student());    // Student:hello

        /*
        相当于:
            Person p = new Student();
            p.hello();
         */
    }

    /**
     * 调用非public方法
     *
     * @throws Exception
     */
    private static void invokePrivateMethod() throws Exception {
        Person p = new Person();
        Method m = p.getClass().getDeclaredMethod("setName", String.class);
        m.setAccessible(true);
        m.invoke(p, "Bob");
        System.out.println(p.name);
    }

    /**
     * 通过反射调用静态方法
     *
     * @throws Exception
     */
    private static void invokeStaticMethod() throws Exception {
        // 获取Integer.parseInt(String)方法,参数为String:
        Method m = Integer.class.getMethod("parseInt", String.class);
        // 调用该静态方法并获取结果:
        Integer n = (Integer) m.invoke(null, "12345");
        // 打印调用结果:
        System.out.println(n);
    }

    /**
     * 通过反射调用类方法
     *
     * @throws Exception
     */
    private static void invokeMethod() throws Exception {
        // String对象:
        String s = "Hello world";
        // 获取String substring(int)方法,参数为int:
        Method m = String.class.getMethod("substring", int.class);
        // 在s对象上调用该方法并获取结果:
        String r = (String) m.invoke(s, 6);
        // 打印调用结果:
        System.out.println(r);
    }

    private static void getMethod() throws Exception {
        Class stdClass = Student.class;
        Method method = stdClass.getMethod("getScore", String.class);

        System.out.println(Arrays.toString(stdClass.getMethods())); // getScore , getName , Object.wait...
        System.out.println(Arrays.toString(stdClass.getDeclaredMethods())); // getGrade , getScore

        // 获取public方法getScore,参数为String:
        System.out.println(method);
        // 获取继承的public方法getName,无参数:
        System.out.println(stdClass.getMethod("getName"));
        // 获取private方法getGrade,参数为int:
        System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));

        /**
         * getName():返回方法名称,例如:"getScore";
         * getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
         * getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
         * getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
         */
        System.out.println(method.getName());
        Class<?> returnType = method.getReturnType();
        Class<?>[] parameterTypes = method.getParameterTypes();
        int modifiers = method.getModifiers();
    }

    static class Student extends Person {
        public void hello() {
            System.out.println("Student:hello");
        }

        public int getScore(String type) {
            return 99;
        }

        private int getGrade(int year) {
            return 1;
        }
    }

    static class Person {

        public void hello() {
            System.out.println("Person:hello");
        }

        private String name = "personName";

        private void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

调用构造方法 Constructor

/**
 * getConstructor(Class...):获取某个public的Constructor;
 * getDeclaredConstructor(Class...):获取某个Constructor;
 * getConstructors():获取所有public的Constructor;
 * getDeclaredConstructors():获取所有Constructor。
 *
 * Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题
 */
public class ConstructorMain {
    public static void main(String[] args) throws Exception {

        // 调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。
        // 如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
        Integer integer = Integer.class.newInstance();
        System.out.println(integer);

        // 获取构造方法Integer(int):
        Constructor cons1 = Integer.class.getConstructor(int.class);
        // 调用构造方法:
        Integer n1 = (Integer) cons1.newInstance(123);
        System.out.println(n1);

        // 获取构造方法Integer(String)
        Constructor cons2 = Integer.class.getConstructor(String.class);
        Integer n2 = (Integer) cons2.newInstance("456");
        System.out.println(n2);
    }
}

动态代理

public class ProxyMain {
    public static void main(String[] args) {
        /**
         * 在运行期动态创建一个interface实例的方法如下:
         * 1. 定义一个InvocationHandler实例,它负责实现接口的方法调用;
         * 2. 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:
         * 2.1. 使用的ClassLoader,通常就是接口类的ClassLoader;
         * 2.2. 需要实现的接口数组,至少需要传入一个接口进去;
         * 2.3. 用来处理接口方法调用的InvocationHandler实例。
         * 3. 将返回的Object强制转型为接口。
         */
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method); // public abstract void reflection.ProxyMain$Hello.morning(java.lang.String)
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]); // Good morning, Bob
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), // 传入ClassLoader
                new Class[]{Hello.class}, // 传入要实现的接口
                handler); // 传入处理调用方法的InvocationHandler
        hello.morning("Bob");
    }

    interface Hello {
        void morning(String name);
    }

    /**
     * 把上面的动态代理改写为静态实现类大概长这样:
     */
    static class HelloDynamicProxy implements Hello {
        InvocationHandler handler;

        public HelloDynamicProxy(InvocationHandler handler) {
            this.handler = handler;
        }

        public void morning(String name) {
            try {
                handler.invoke(this, Hello.class.getMethod("morning", String.class), new Object[]{name});
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
}

参考资料

posted @ 2022-02-10 21:23  流星<。)#)))≦  阅读(51)  评论(0编辑  收藏  举报