Java 反射技术

       Java 反射技术应用广泛,它能够配置:类的全限定名、方法和参数,完成对象的初始化,甚至是反射某些方法。这样就可

以大大增强 Java 的可配置性,Spring IoC 的基本原理也是如此,当然 Spring IoC 的代码要复杂的多。

        Java 的反射内容繁多,包括对象构建、反射方法、注解、参数、接口等。本文主要讲解对象构建(包括没有参数的和有

参数的构建方法)和方法的反射调用。

        在 Java 中,反射是通过包 java.lang.reflect.* 来实现的。

1.通过反射构建对象


    1.1通过反射构建对象(无参)

public class ReflectServiceImpl {

public ReflectServiceImpl getInstance() {

ReflectServiceImpl object = null;

try {
object = (ReflectServiceImpl) Class.forName("ReflectServiceImpl").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}
}
        这里是一个构建方法,没有任何参数的类的反射生成。这里的代码就会生成一个对象,然后将其返回。加粗的代码是主要的代码片段,它的目的就是给类加载器注册了一个 ReflectServiceImpl 的全限定名(这里因为没有建包,所以是默认的),然后通过 newInstance 方法初始化了一个类对象。

    1.2.通过反射构建对象(有参)

import java.lang.reflect.InvocationTargetException;

public class ReflectServiceImpl2 {

private String name;

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

public ReflectServiceImpl2 getInstance() {
ReflectServiceImpl2 object = null;
try {
object = (ReflectServiceImpl2) Class.forName("ReflectServiceImpl").getConstructor(String.class).newInstance("田七");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}
}

        这里就实现了一个含有参数的构建方法,加粗的代码是主要的代码片段,先通过 forName 加载到类的加载器,然后通过 getConstructor 方法,它的参数可以是多个,这里定义为 String.class,意为有且只有一个参数类型为 String 的构建方法。通过这个方法可以对重名方法进行排除,此时再用 newInstance 方法生成对象,只是 newInstance 方法也多了一个参数 “田七” 而已。

        实际就等于 object = new ReflectServiceImpl2("田七");,只是这里使用反射机制来生成这个对象而已。

2.通过反射来反射方

        着重介绍如何使用反射方法。在使用反射方法前我们需要获取方法对象,得到了方法才能够去反射。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectMethod {

private String name;

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

public Object reflectMethod() {
Object returnObj = null;
ReflectMethod target = new ReflectMethod();
try {
Method method = ReflectMethod.class.getMethod("sayHello", String.class);
returnObj = method.invoke(target, "田七");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return returnObj;
}
}
        我们来看看加粗的代码,当有具体的对象 target 时,而不知道具体是哪个类时,也可以使用 target.getClass().getMethod("sayHello",String.class); 代替它,其中第一个参数是方法的名称,第二个参数是参数的类型,是一个列表,对个参数可以继续编写多个类型,这样便能获得反射的方法对象。反射方法是运用 returnObj = method.invoke(target,"田七");代码完成的,第一个参数为 target,就是确定用哪个对象调用方法,而 "田七" 是参数,这行就等同于 target.sayHello("田七");。如果存在多个参数,可以写成 Method.invoke(target,obj1,obj2,obj3...),这些要根据对象的具体方法来确定。
总结:
        反射的优点是只要配置就可以生成对象,可以解除程序的耦合度,比较灵活。反射的缺点是运行比较慢。但是大部分情况下为了灵活性,降低程序耦合度,我们还是会使用反射的,比如 Spring IoC容器。




猜你喜欢

转载自blog.csdn.net/zhichunqi/article/details/80062375
今日推荐