返回 登录
0

Java 反射,开发框架必备技能

学习Java的同学注意了!!!
学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java!

反射一般开发者接触不到,反射主要用户框架的开发。例如我举一个例子你就明白了:
http://www.netkiller.cn/news/list/2.html
通过反射技术我们将上面的统一资源定位付(URL) 映射到Class 相当于
class: news
method: list
parameter: 2
差不多就是下面样子

class News{
    public String list(String catagory_id){
        ...
        ...
    }
}

我们只需要在框架核心中分析 url 然后调用对应的方法,于此同时将参数传递过去。

Class<?> cls = Class.forName("cn.netkiller.reflect.News");
        Object obj= cls.newInstance();
        Method method = cls.getDeclaredMethod("list", int.class);
        return method.invoke(obj, 2);

本文节选自《Netkiller Java 手札》
1.9. Reflection 反射
this.getClass().getName() //当前Class名字
Thread.currentThread().getStackTrace()[1].getMethodName()); //当前方法名
1.9.1. 获得所有变量

    Field[] fields = objClass.getFields();
    for (Field field : fields) {
        System.out.println(field.getName());
    }   

注意:只能去除 public变量
1.9.2. 批量赋值
1.9.3. 方法操作
JAVA反射调用方法的步骤有三步
得到要调用类的class
得到要调用的类中的方法(Method)
方法调用(invoke)
1.9.3.1. 获得所有方法

    Class<?> objClass = a.getClass();
    Method[] methods =  objClass.getDeclaredMethods();
    for (Method method : methods) {
        System.out.println(method);
    }   

1.9.3.2. set/get 方法

package cn.netkiller.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Member {
    public String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "ClassA [name=" + name + ", age=" + age + "]";
    }

    public Member() {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> cls = Class.forName("cn.netkiller.reflect.Member");
        Object member = cls.newInstance();
        Method setMethod = cls.getDeclaredMethod("setAge", int.class);
        setMethod.invoke(member, 15);

        Method getMethod = cls.getDeclaredMethod("getAge");
        System.out.println(getMethod.invoke(member));

    }

}           

下面做一个稍微复杂点的例子,ClassB继承ClassA,取出ClassA的成员变量赋值到ClassA。

            package cn.netkiller.reflect;

public class ClassA {
    public String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public ClassA() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public String toString() {
        return "ClassA [name=" + name + ", age=" + age + "]";
    }
}

package cn.netkiller.reflect;

public class ClassB extends ClassA{

    public ClassB() {
        // TODO Auto-generated constructor stub
    }
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "ClassB [address=" + address + "]";
    }

}


package cn.netkiller.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionTest {

    public ReflectionTest() {
        // TODO Auto-generated constructor stub
    }

    public void testSetMethod() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {

        // ClassA a = new ClassA();

        ClassB b = new ClassB();
        b.setAddress("Shenzhen");

        Class<ClassA> classA = ClassA.class;
        ClassA a = classA.newInstance();
        a.setName("Neo");
        a.setAge(30);

        System.out.println(classA.getDeclaredMethod("getAge").invoke(a));

        Method m = classA.getDeclaredMethod("setAge", int.class);
        m.setAccessible(true); // 因为写成private 所以这里必须设置
        m.invoke(b, 26);

        System.out.println(a.toString());
        System.out.println(b.toString());

        System.out.println(b.getName());
        System.out.println(b.getAge());
    }

    public static void main(String[] args) throws InvocationTargetException {

        ReflectionTest rt = new ReflectionTest();
        try {
            rt.testSetMethod();

        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

set 方法

System.out.println(classA.getDeclaredMethod("getAge").invoke(a));   

get 方法

Method m = classA.getDeclaredMethod("setAge", int.class);
m.setAccessible(true);  //因为写成private 所以这里必须设置
m.invoke(b, 26);    

1.9.3.3. static 方法调用

            Class cls = Class.forName("cn.netkiller.reflect.Student");
Method setMethod = cls.getDeclaredMethod("setAge",int.class);
setMethod.invoke(cls.newInstance(), 15);

static 方法调用时,不必得实例化对象

            Class cls = Class.forName("cn.netkiller.reflect.Student");
Method staticMethod = cls.getDeclaredMethod("setAge",int.class);
staticMethod.invoke(cls,20); //这里不需要newInstance

学习Java的同学注意了!!!
学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java!

评论