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.通过反射构建对象(有参):
扫描二维码关注公众号,回复:
909594 查看本文章
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容器。 |