欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java反射学习

程序员文章站 2024-01-21 14:40:16
...

Java的反射技术应用广泛,它能够配置:类的权限定名、方法和参数,完成对象的初始化,甚至是反射某些方法。这样就可以大大增强Java的可配置性,Spring IoC的基本原理也是如此,当然Spring IoC的代码要复杂的多。

Java的发射内容繁多,包括对象的构造、反射方法、注释、参数、接口等。本人最近学习了对象构建和方法的反射调用,主要从这两方面来撰写该文章。在Java中,反射是通过包java.lang.reflect.*实现的。

一、通过反射构建对象

(一)无参构造对象

在Java中允许通过反射配置信息和构建对象,代码如下所示:

public void sayHello(String name) {
        System.out.println("Hello Reflect " + name);
    }

然后通过反射的方法构造它,代码如下所示:

public ReflectServiceImpl getInstance() {
        ReflectServiceImpl reflectServiceImpl = null;
        try {
            reflectServiceImpl = (ReflectServiceImpl)Class.forName("com.chenbin.reflect.ReflectServiceImpl")
                    .newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reflectServiceImpl;
    }

这里的代码就是生成一个对象,然后将其返回。下面这段代码的目的就是给类加载器注册了一个类ReflectServiceImpl的全限定名,然后通过newInstance方法初始化了一个类对象,使用反射的方式也是什么简单。

reflectServiceImpl = (ReflectServiceImpl)Class.forName("com.chenbin.reflect.ReflectServiceImpl")
                    .newInstance();

(二)有参构造对象

以上是没有任何参数的类的反射生成,如果一个类的所有构造方法里都至少存在一个参数,如何用反射构造它。在Java中,只要稍微改变一下就可以了,代码如下所示:

public class ReflectServiceImpl2 {

    private String name;

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

    public void sayHello() {
        System.out.println("Hello " + name);
    }
}

这里实现了含有一个参数的构造方法,这时将不能用之前的办法将其反射生成对象,用一下代码可以完成相同的功能,代码如下所示:

public ReflectServiceImpl2 getInstance() {
        ReflectServiceImpl2 reflectServiceImpl2 = null;
        try {
            reflectServiceImpl2 = (ReflectServiceImpl2)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2")
                    .getConstructor(String.class).newInstance("张三");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reflectServiceImpl2;
    }

使用如下代码反射生成对象:

 reflectServiceImpl2 = (ReflectServiceImpl2)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2")
                    .getConstructor(String.class).newInstance("张三");

先通过forName加载到类的加载器。然后通过getConstructor方法,它的参数可以是多个、还可以是实体对象,这里定义为String.class,意为有且只有一个参数类型为String的构建方法。通过这个方法可以对重名方法进行排除,此时再用newInstance方法生成对象,只是newInstance方法也多一个参数"张三"而已。实际等于reflectServiceImpl2 = new ReflectServiceImpl2("张三"),只是这里用反射机制来生成这个对象而已。

反射的优点是只要配置就可以生成对象,可以解除程序的耦合度,比较灵活。反射的缺点是运行比较慢。但是大部分情况下为了灵活,降低程序的耦合度,我们还是会使用反射的,比如Spring IoC容器。

二、反射方法

以下主要介绍反射方法,在使用反射方法前要获取方法对象,得到了放大才能够反射,代码如下所示:

public Object reflectMethod() {
        Object returnObj = null;
        ReflectServiceImpl reflectServiceImpl = new ReflectServiceImpl();
        try {
            Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
            returnObj = method.invoke(reflectServiceImpl,"张三");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnObj;
    }

我们来看这段代码Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);当有具体的对象target,而不知道具体是哪个类时,也可以使用target.getClass.getMethod("sayHello"。String.class)代替它,其中第一个参数是方法名称,第二个参数是参数类型,是一个列表,多个参数可以继续编写多个类型,这样便能获得反射的方法对象。反射方法是运用returnObj = method.invoke(target,"张三");代码完成的,第一个参数为target,就是确定用哪个对象调用方法,而"张三"是参数,这行就等同于target.sayHello("张三");。如果存在多个参数,可以写成Method.invoke(target,obj1,obj2,obj3...),这些要根据对象的具体方法来确定。

实例:

通过实例来看看如何反射生成对象和反射调度方法,代码如下所示:

public Object reflect() {

        ReflectServiceImpl object = null;
        try {
            object = (ReflectServiceImpl)Class.forName("com.chenbin.reflect.ReflectServiceImpl")
                    .newInstance();
            Method method = object.getClass().getMethod("sayHello", String.class);
            method.invoke(object,"张三");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }

以上就是对反射的学习,希望对看到的大家有所帮助,后续会学习Java设计模式,文章会持续更新哦,记得关注哟!

上一篇: JAVA反射

下一篇: 权限过滤器