Java反射机制

                     Java反射机制

反射概念:(百度百科)JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

作用:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

反射机制在API 需要的类:
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

下面我们通过几个实例来描述java反射机制都能做哪些事情。

利用反射机制对ReflectTester类的customer对象进行拷贝:

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

public class ReflectTester {
    // 该方法实现对 customer对象的拷贝
    public Object copy(Object object) throws Exception {
        Class<?> classType = object.getClass();//获得 Object类的类对象

        Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
        // 先通过类对象对不带参数的构造方法获得其constructor对象,再通过构造方法对象
        // 调用实例化方法生成对customer类的对象,并转成object类型的 所以objectCopy是object类型的引用
        // ,但指向customer类,也就是多态。
        // Object object2=classType.newInstance();上面两句等同于这一句

        Field[] fields = classType.getDeclaredFields(); // 获得指定类(Object)的所有成员变量

        for (Field field : fields) { // 增强的for循环 对存储customer成员变量的数组进行遍历 ,并打印输出
            String name = field.getName();

            String firstLetter = name.substring(0, 1).toUpperCase();// substring方法是获得对应字符串的在该下标范围内的字符 [0,1)
                                                                    // toUpperCase方法是将属性的首字母转换成大写

            String getMethodName = "get" + firstLetter + name.substring(1);// 这个1表示1到末尾的字符
            String setMethodName = "set" + firstLetter + name.substring(1);//字符串拼接

            Method getMethod = classType.getMethod(getMethodName, new Class[] {});// customer类里面的getName方法是无参方法,获得指定方法的方法对象,括号内的getMethodName就是我们想要获得的方法的方法名,后面的Class类的数组就是该方法的参数
            Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });// setMethodName方法是有参方法,getType方法是返回field的类型

            Object value = getMethod.invoke(object, new Object[] {});// 这里的object是一开始传入的customer,getName方法无参,也就是通过invoke方法调用指定的方法,也就是Customer类里面的所有成员变量的get方法,最后得到object对象里面的具体数值信息然后赋给value对象,

            setMethod.invoke(objectCopy, new Object[] { value });// 将value里面的值传给objectCopy对象,通常情况下只要我们new一个对象,该对象里面都会包含一份对应类的成员变量,我们将面从get方法里面返回的数值重新赋给objectCopy里面的成员变量,也就完成了copy操作
        }

        return objectCopy;
    }

    public static void main(String[] args) throws Exception {
        Customer customer = new Customer("Tom", 20);
        customer.setId(1L);

        ReflectTester test = new ReflectTester();

        Customer customer2 = (Customer) test.copy(customer);

        System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());
    }
}

class Customer {
    private Long id;

    private String name;

    private int age;

    public Customer() {

    }

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    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;
    }
}  

代码中的注释对代码解释已经很详细我就不在说了。接下来在看第二个例子,功能是实现调用某类的方法:

这里写import java.lang.reflect.Method;

public class InvokeTester
{
    public int add(int param1, int param2)
    {
        return param1 + param2;
    }

    public String echo(String message)
    {
        return "hello: " + message;
    }

    public static void main(String[] args) throws Exception
    {
        // InvokeTester test = new InvokeTester();
        // System.out.println(test.add(1, 2));
        // System.out.println(test.echo("tom"));
        //下面那么多行代码其实就等同于上面几行代码
        Class<?> classType = InvokeTester.class;//获得对应类的类对象

        Object invokeTester = classType.newInstance();//获得指定类的实例

        // System.out.println(invokeTester instanceof InvokeTester);

        Method addMethod = classType.getMethod("add", new Class[] { int.class,int.class });//通过括号内的限制,获得指定方法的方法对象

        Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});//对指定方法进行调用,

        System.out.println(result);

        System.out.println("---------------------");

        Method echoMethod = classType.getMethod("echo", new Class[]{String.class});

        Object result2 = echoMethod.invoke(invokeTester, new Object[]{"tom"});

        System.out.println((String)result2);

    }
}

再看第三个例子,功能是给某类的私有变量赋值:

public class Private2
{
    private String name = "zhangsan";

    public String getName()
    {
        return name;
    }
}

import java.lang.reflect.Field;

public class TestPrivate2
{
    public static void main(String[] args) throws Exception
    {
        Private2 p = new Private2();

        Class<?> classType = p.getClass();//获得指定类的类对象

        Field field =classType.getDeclaredField("name");//获得指定类里面的指定成员变量

        field.setAccessible(true);//这里很重要,这里就使我们为什么能对私有化成员变量进行修改的主要原因,不明白得就去查看API文档

        field.set(p, "lisi");//修改指定成员变量的值

        System.out.println(p.getName());
    }
}

下一个例子是通过反射构建数组

import java.lang.reflect.Array;

public class ArrayTester1 {


    public static void main(String[] args) throws Exception {
        Class<?>classTypeClass.forName("java.lang.String");//根据后面的字符串获得指定类的类对象

        Object  array = Array.newInstance(classType, 10);//这里的classtype是String,这句话的意思是创建一个String类型长度为10的数组
        System.out.println(array instanceof String[]);
        for(int i=0;i<Array.getLength(array);i++) {
            String str = (String) Array.get(array, i);
            System.out.println(str);
        }
        Array.set(array, 5, "hello");//对数组某个位置上添加元素

        String str = (String) Array.get(array, 5);

        System.out.println(str);
    }
}

也不知道你们有没有耐心看到这里。。。。。。。

最后我就在总结一下反射机制的用法:

一般情况下 只要使用反射机制,我们都会先获得对应类的类对象,而获得类对象有三种方法:

a)使用 Class 类的静态方法 forName:Class.forName(“java.lang.String”);

b)使用类的.class 语法:String.class;

c)使用对象的 getClass()方法:String s = “aa”; Class<?> clazz = s.getClass();

若想通过类的不带参数的构造方法来生成对象,我们有两种方式:

a)先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可:

Class<?> classType = String.class; Object obj = classType.newInstance();

b)先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor 对象的 newInstance()方法生成:

Class<?> classType = Customer.class;

Constructor cons = classType.getConstructor(new Class[]{}); Object obj = cons.newInstance(new Object[]{});

若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:

Class<?> classType = Customer.class;

Constructor cons = classType.getConstructor(new Class[]{String.class, int.class}); Object obj = cons.newInstance(new Object[]{“hello”, 3});

至于一些其他的方法也基本都在上面代码中,我就不在一一列出来。
不正确的地方大家多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值