JavaSE---反射(未完待续)

Posted anpeiyong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE---反射(未完待续)相关的知识,希望对你有一定的参考价值。

 

java.lang.reflect包下接口及类

  Class、Method、Field、Constructor、Array...

  Java程序 可以使用 这些 类 动态 获取 某个对象、某个类 运行时信息; 

              动态 创建 Java对象、动态 调用Java方法、 动态 访问并修改指定对象的属性值

  Type

    Class所实现的接口;

  ParameterizedType

    代表一个带泛型参数的类型;

  Proxy 与 InvocationHandler

    使用 Proxy 与 InvocationHandler 创建JDK动态代理;

 

类的唯一标识

  同一个JVM进程中: 全限定类名 (包名 + 类名)+ 类加载器 ;

 

Java程序中 许多对象 运行时 有2种类型:编译时类型、运行时类型,需要 在 运行时 发现 对象的真实信息,有2种做法:

  1、编译、运行时 完全知道类型的具体信息

      instaceof 类型判断--->类型强转--->使用

  2、编译时无法预知类型

      只能依赖运行时信息发现 真实信息,使用反射;

 

    1.2  获得Class对象

          每个类被加载后,在内存中都会创建一个该类的Class对象,通过Class对象就可以访问JVM中的这个类;

          1.1.1  调用Class对象的forName(),返回该类的Class对象  public static Class<?> forName(String className)

                className:类的全限定名

          1.1.2  调用某个类的class属性,将返回该类的Class对象; 

          1.1.3  调用某个类的getClass(),将返回该类的Class对象;

    1.3  从Class对象中获取信息   

          1.1.1  访问Class对应类包含的构造器

                                         

          1.1.2   访问Class对应类包含的方法

                                        

          1.1.3  访问Class对应类包含的属性

                                       

          1.1.4  访问Class对应类上的注解

                                  

          1.1.5  访问Class对应类包含的内部类

                                   

          1.1.6  访问Class对应类包含的外部类

                                     

          1.1.7  访问Class对应类所继承的父类、实现的接口

                                   

          1.1.8  判断Class对应类是接口、注解、枚举等

                   

     1.4  使用反射生成并操作对象          

package com.an.reflect;

/**
 * @author apy
 * @description
 * @date 2021/5/6 14:28
 */
public class A {
    private String name;
    private String job;

    public A(){

    }

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

    public String getName() {
        return name;
    }

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

    private void setJob(String job){
        this.job = job;
    }

    public String getJob(){
        return job;
    }
    
}



package com.an.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author apy
 * @description
 * @date 2021/5/6 11:04
 */
public class Test {

    public static void main(String[] args) {
        testReflect();
    }

    /**
     * 1、获取Class对象
     * 2、对象创建
     * 3、调用方法
     * 4、访问属性值
     */
    public static void testReflect(){
        try {
            // 1、根据全限定名 找到JVM中对应的Class对象
            Class aClass = Class.forName("com.an.reflect.A");

            // 2.1、调用无参构造
            Object instance = aClass.newInstance();

            // 2.2、调用String参数构造
            Constructor stringConstructor = aClass.getConstructor(String.class);
            Object instance1 = stringConstructor.newInstance("jack");

            // 3.1、调用public方法
            Method[] methods = aClass.getMethods();
            for (Method m:methods) {
                System.out.println("methods:"+m);
            }
            /**
             * 结果:
             * methods:public java.lang.String com.an.reflect.A.getJob()
             * methods:public java.lang.String com.an.reflect.A.getName()
             * methods:public void com.an.reflect.A.setName(java.lang.String)
             * methods:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
             * methods:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
             * methods:public final void java.lang.Object.wait() throws java.lang.InterruptedException
             * methods:public boolean java.lang.Object.equals(java.lang.Object)
             * methods:public java.lang.String java.lang.Object.toString()
             * methods:public native int java.lang.Object.hashCode()
             * methods:public final native java.lang.Class java.lang.Object.getClass()
             * methods:public final native void java.lang.Object.notify()
             * methods:public final native void java.lang.Object.notifyAll()
             */
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method m:declaredMethods) {
                System.out.println("declaredMethods:"+m);
            }
            /**
             * 结果:
             * declaredMethods:public java.lang.String com.an.reflect.A.getJob()
             * declaredMethods:private void com.an.reflect.A.setJob(java.lang.String)
             * declaredMethods:public java.lang.String com.an.reflect.A.getName()
             * declaredMethods:public void com.an.reflect.A.setName(java.lang.String)
             */
            Method publicSetNameMethod = aClass.getMethod("setName", String.class);
            publicSetNameMethod.invoke(instance, "rose");

            //3.2、调用private方法
            //      使用 Method的invoke方法 要求有该方法的权限;
            //      若想调用某个对象的private方法,可以先调用 Method的setAccessible方法
            //          值为true时,在使用时将取消 Java语言访问权限检查
            //          值为false时,在使用时将实施 Java语言访问权限检查

            Method privateSetJobMethod = aClass.getDeclaredMethod("setJob", String.class);
            privateSetJobMethod.setAccessible(true);
            privateSetJobMethod.invoke(instance, "teacher");
            Field privateJobField = aClass.getDeclaredField("job");
            privateJobField.setAccessible(true);
            System.out.println("instance.job:"+privateJobField.get(instance));

            // 4、访问属性值
            Field[] fields = aClass.getFields();
            for (Field f:fields) {
                System.out.println("getFields:"+f.getName());
            }
            /**
             * 结果:无
             */

            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field f:declaredFields) {
                System.out.println("getDeclaredFields:"+f.getName());
            }
            /**
             * 结果:
             * getDeclaredFields:name
             * getDeclaredFields:job
             */

            //  4.1、访问private属性
            //      若想调用某个对象的private属性,可以先调用 Method的setAccessible方法
            //          值为true时,在使用时将取消 Java语言访问权限检查
            //          值为false时,在使用时将实施 Java语言访问权限检查
            Field privateNameField = aClass.getDeclaredField("name");
            privateNameField.setAccessible(true);
            System.out.println("Field.set pre:"+privateNameField.get(instance));
            privateNameField.set(instance, "rose1");
            Object o = privateNameField.get(instance);
            System.out.println("Field.get:"+o);
            /**
             * 结果:
             * Field.set pre:rose
             * Field.get:rose1
             */

        }catch (ClassNotFoundException e){
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

  

JDK动态代理

package com.an.reflect;

/**
 * @author apy
 * @description
 * @date 2021/5/6 15:50
 */
public interface B {
    void say(String name);
}


package com.an.reflect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author apy
 * @description
 * @date 2021/5/6 15:52
 */
public class BProxy implements InvocationHandler {
    /**
     * @param proxy 代理对象
     * @param method 正在执行的方法
     * @param args 正在执行方法的参数
     * @return
     * @throws Throwable
     *
     * 结果:
     * 代理对象:class com.sun.proxy.$Proxy0
     * 正在执行的方法:say
     * 正在执行的方法参数:
     * hello,
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理对象:"+proxy.getClass());
        System.out.println("正在执行的方法:"+method.getName());
        System.out.println("正在执行的方法参数:");
        for (Object o:args) {
            System.out.println(o+",");
        }
        return null;
    }
}


package com.an.reflect;

import java.lang.reflect.*;

/**
 * @author apy
 * @description
 * @date 2021/5/6 11:04
 */
public class Test {

    public static void main(String[] args) {
        testDynamicProxy();
    }

    /**
     * JDK动态代理:
     *      为 一个或多个接口  创建代理类 | 代理对象
     *      提供Proxy、InvocationHandler
     */
    private static void testDynamicProxy() {
        Object proxyInstance = Proxy.newProxyInstance(B.class.getClassLoader(), new Class[]{B.class}, new BProxy());
        B b = (B) proxyInstance;
        b.say("hello");
    }
}

 

反射与泛型

package com.an.reflect;

import java.util.Map;

/**
 * @author apy
 * @description
 * @date 2021/5/6 14:28
 */
public class A {
    private String name;
    private String job;
    private Map<String,Integer> map;

    public A(){

    }

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

    public String getName() {
        return name;
    }

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

    private void setJob(String job){
        this.job = job;
    }

    public String getJob(){
        return job;
    }
}


package com.an.reflect;

import java.lang.reflect.*;

/**
 * @author apy
 * @description
 * @date 2021/5/6 11:04
 */
public class Test {

    public static void main(String[] args) {
        testGenericProxy();
    }

    /**
     * 反射与泛型
     */
    private static void testGenericProxy() {
        try {
            Class aClass = Class.forName("com.an.reflect.A");
            Field privateJobField = aClass.getDeclaredField("job");
            Class<?> privateJobFieldType = privateJobField.getType();
            System.out.println("job type:"+privateJobFieldType);

            Field privateMapField = aClass.getDeclaredField("map");
            Type genericType = privateMapField.getGenericType();
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            Type rawType = parameterizedType.getRawType();// 返回被泛型限制的类型
            System.out.println("map rawType:"+rawType);
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();// 返回泛型参数类型
            System.out.println("map actualTypeArguments:");
            for (Type t:actualTypeArguments) {
                System.out.println(t+",");
            }
        } catch (ClassNotFoundException | NoSuchFieldException e) {
            e.printStackTrace();
        }
        /**
         * 结果:
         * job type:class java.lang.String
         * map rawType:interface java.util.Map
         * map actualTypeArguments:
         * class java.lang.String,
         * class java.lang.Integer,
         */

    }
}

  

 

 

                    

以上是关于JavaSE---反射(未完待续)的主要内容,如果未能解决你的问题,请参考以下文章

Java/计算机网络/操作系统面试题总结(未完待续)

Python之路第一课Day6--随堂笔记(面向对象编程进阶...未完待续 )

读caffe源码(未完待续)

浅析Socket建立过程(未完待续)

JavaScript 进阶(未完待续)

实验报告 四(未完待续)