Java反射机制

Posted one-reader

tags:

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

一、什么是反射?

Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
简单来说,就是java反射机制可以在运行阶段,基于编译阶段的class对象,动态的创建对象,获取类的完整结构。

二、反射的使用

定义一个类:

public class ReflectionDemo 

    public String username;

    private Integer password ;


    public ReflectionDemo() 

    

    public ReflectionDemo(String name) 
        System.out.println(name);
    

    public void say() 
        System.out.println("hello!");
    

    public void talk(String name, Integer age) 
        System.out.println(name + "今年:" + age + "岁!");
    


获取类型

       /**
         * 获取类对象的三种方式
         */
        //1.通过对象的getClass()方法获取
        ReflectionDemo rd = new ReflectionDemo();
        Class<? extends ReflectionDemo> aClass = rd.getClass();
        System.out.println("通过对象的getClass()方法获取:"+aClass);
        //2.通过类名的class
        Class<? extends ReflectionDemo> aClass1 = ReflectionDemo.class;
        System.out.println("通过类名的class: "+aClass1);
        //3.通过Class.forName()
        try 
            Class<?> aClass2 = Class.forName("com.my.reflection.ReflectionDemo");
            System.out.println("Class.forName():"+aClass2);
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        

运行结果:

通过对象的getClass()方法获取:class com.my.reflection.ReflectionDemo
通过类名的class: class com.my.reflection.ReflectionDemo
Class.forName():class com.my.reflection.ReflectionDemo

获取属性

            /**
             * 反射 获取成员变量
             * Field getField(String name)  根据变量名,返回一个具体的具有public属性的成员变量
             * Field[] getFields()  返回具有public属性的成员变量的数组
             * Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
             * Field[] getDelcaredFields() 返回所有成员变量组成的数组(不分public和非public属性)
             */
            Class class4 = null;
            try 
                //获取类对象
                class4 = Class.forName("com.my.reflection.ReflectionDemo");
                //获取属性
                Field field1 = class4.getField("username");
                System.out.println("field1=" + field1.getName());
                Field field2 = class4.getDeclaredField("password");
                System.out.println("field2=" + field2.getName());
                System.out.println("*******************");
                // 使用getFields获取属性
                Field[] fields = class4.getFields();
                for (Field f : fields) 
                    System.out.println(f);
                
                System.out.println("*******************");
                // 使用getDeclaredFields获取属性
                fields = class4.getDeclaredFields();
                for (Field f : fields) 
                    System.out.println(f);
                

运行结果:

field1=username
field2=password
*******************
public java.lang.String com.my.reflection.ReflectionDemo.username
*******************
public java.lang.String com.my.reflection.ReflectionDemo.username
private java.lang.Integer com.my.reflection.ReflectionDemo.password

获取类的方法

/**
* 反射 调用 对象方法
* Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
* Method[] getMethods() 返回所有具有public属性的方法数组
* Method getDeclaredMethod(String name, Class[] params)  根据方法名和参数,返回一个具体的方法(不分public和非public属性)
* Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
*/
Class class3 = null;
try 
       class3 = Class.forName("com.my.reflection.ReflectionDemo");
       Method method = class3.getMethod("talk", String.class,Integer.class);
       Object object = class3.newInstance();
       method.invoke(object, "老王",18);
    catch (ClassNotFoundException e) 
       e.printStackTrace();
    catch (NoSuchMethodException e) 
       e.printStackTrace();
    catch (IllegalAccessException e) 
       e.printStackTrace();
    catch (InstantiationException e) 
       e.printStackTrace();
    catch (InvocationTargetException e) 
       e.printStackTrace();
   

运行结果:

老王今年:18岁!

获取类的Constructor

       /**
        * 反射通过无惨构造实例对象
        */
        Class class1 = null;
        try 
            class1 = Class.forName("com.my.reflection.ReflectionDemo");
            Object object = class1.newInstance();
            ReflectionDemo reflectionDemo = (ReflectionDemo) object;
            reflectionDemo.say();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
         catch (InstantiationException e) 
            e.printStackTrace();
        

        /**
         * 反射通过构造实例对象
         * Constructor getConstructor(Class[] params)根据构造函数的参数,返回一个具体的具有public属性的构造函数
         * Constructor getConstructors()     返回所有具有public属性的构造函数数组
         * Constructor getDeclaredConstructor(Class[] params)     根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
         * Constructor getDeclaredConstructors()    返回该类中所有的构造函数数组(不分public和非public属性)
         */
        Class class2 = null;
        try 
            class2 = Class.forName("com.my.reflection.ReflectionDemo");
            Constructor constructor = class2.getConstructor(String.class);
            Object object = constructor.newInstance("abc");
            ReflectionDemo reflectionDemo = (ReflectionDemo) object;
            reflectionDemo.say();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (NoSuchMethodException e) 
            e.printStackTrace();
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
        

运行结果

hello!
abc
hello!

动态Proxy

java.lang.reflect.Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类

InvocationHandler
是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

UserService接口

public interface UserService 
    String getName(String name);

UserService实现

public class UserServiceImpl implements UserService 

    public String getName(String name) 
        System.out.println(name);
        return "getName";
    

MyInvocationHandler代理类

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

/**
 * jdk动态代理
 * @author onereader
 */
public class MyInvocationHandler implements InvocationHandler 
    //目标对象
    private Object target;

    public MyInvocationHandler() 
        super();
    

    public MyInvocationHandler(Object target) 
        super();
        this.target = target;
    

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable 
        if (method.getName().equals("getName")) 
            System.out.println("++++++before " + method.getName() + "++++++");
            Object result = method.invoke(target, args);
            System.out.println("++++++after " + method.getName() + "++++++");
            return result;
         else 
            Object result = method.invoke(target, args);
            return result;
        
    


MainTest 类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MainTest 
    public static void main(String[] args) 
        UserService userService = new UserServiceImpl();
        InvocationHandler invoke = new MyInvocationHandler(userService);
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(), invoke);
        System.out.println(userServiceProxy.getName("123"));

    

运行结果:

++++++before getName++++++
123
++++++after getName++++++
getName

三、总结
对于反射,简单来说就是可以再运行时,可以获取到这个类的完整信息。并且创建一个满足自己需要的对象,进行操作。总的来说,学会后使用起来真心很方便~~~ 至于反射的不好地方,我这里不熬诉了,有兴趣自行百度学习~

以上是关于Java反射机制的主要内容,如果未能解决你的问题,请参考以下文章

java 中反射机制和内省机制的区别是啥?

java反射机制

请问java中的反射机制与用法

如何利用java的反射机制动态创建对象

Java反射机制详解

Java反射机制详解