HelloStranger

每个人都是初学者

Java反射技术初涉

Java反射技术

Java反射技术应用广泛,它能够配置:

  • 类的全限定名,方法和参数
  • 完成对象的初始化
  • 反射某些方法

反射内容有:

  • 对象构建
  • 反射方法
  • 注解
  • 参数
  • 接口

本文主要针对下面两个方面:

  • 对象构建(有参数、没参数)
  • 方法的反射

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

反射的优点是只要配置就可以生成对象,可以降低程序的耦合度,比较灵活。

反射的缺点就是运行比较慢。但是大部分情况下为了灵活性,降低程序的耦合度,我们还是会使用反射的,比如SpringIoC容器。

通过反射构建对象

无参数类

在Java中允许通过反射配置信息构建对象,比如下面的ReflectServiceImpl类:

package com.lean.ssm.chapter2.reflect;
/**
 * Created by mzg on 2017/12/5.
 */
public class ReflectServiceImpl {

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

通过反射的方法去构建,如下:

//通过反射的方法构建类,无参数
public ReflectServiceImpl getInstance(){
    ReflectServiceImpl object = null;
    try{
        object = (ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl" ).newInstance();
    }catch (ClassNotFoundException|InstantiationException|IllegalAccessException ex){
        ex.printStackTrace();
    }
    return object;
}

重点构建语句:

object = (ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl" ).newInstance();

 

有参数类

有参数类ReflectServiceImpl2:

package com.lean.ssm.chapter2.
/**
 * Created by mzg on 2017/12/5.
 */
public class ReflectServiceImpl2 {
    private String name;

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

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

实现一个含参数的构建方法:

//通过反射的方法构建类,有参数
public ReflectServiceImpl2 getInstance(){
   ReflectServiceImpl2 object = null;
    try {
        object = (ReflectServiceImpl2)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2").getConstructor(String.class).newInstance("张三");
    } catch (InstantiationException|IllegalAccessException|InvocationTargetException|NoSuchMethodException|ClassNotFoundException e) {
        e.printStackTrace();
    }
    return object;
}

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

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

过程:

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

反射方法

继续以ReflectServiceImpl类为例,代码如下;

/**
 * 类 : ReflectServiceImpl   反射方法
 * @return 方法返回值
 */
public Object reflectMethod(){
    Object returnObj = null;
    ReflectServiceImpl target = new ReflectServiceImpl();
    Method method = null;
    try {
        method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
        returnObj = method.invoke(target,"张三");
    } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
        e.printStackTrace();
    }
    return returnObj;
}

对于代码:

method = ReflectServiceImpl.class.getMethod("sayHello", String.class);

当有具体的对象target,而不知道具体是那个类时,也可以使用 target.getClass().getMethod("sayHello",String.class)代替他。

方法 getMethod("sayHello",String.class):

  • 第一个参数是方法名称
  • 第二个参数是参数类型,是一个列表,多个参数可以继续编写多个类型

方法 returnObj = method.invoke(target,"张三"):

  • 第一个参数为target,就是确定那个对象调用方法
  • 第二个参数为”张三”,等同于 target.sayHello(“张三”)
  • 如果存在多个参数,可以写成Method.invoke(target,obj1,obj2,obj3……)

实例

反射生成对象和反射调度方法的实例,继续以ReflectServiceImpl类为例:

public static Object reflectEx1(){
    ReflectServiceImpl object =null;
    try {
        object = (ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance();
        Method method = object.getClass().getMethod("sayHello", String.class);
        method.invoke(object,"张三");
    } catch (InstantiationException|IllegalAccessException|ClassNotFoundException|NoSuchMethodException|SecurityException|
            IllegalArgumentException|InvocationTargetException e) {
        e.printStackTrace();
    }
    return object;
}
点赞

发表评论