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

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

转载于:https://www.cnblogs.com/one-reader/p/11521236.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值