反射的应用

作者: 风吹稻子 | 来源:发表于2017-04-13 10:16 被阅读39次

反射基础知识链接:http://www.jianshu.com/p/370073fad7e3

反射应用的场景

  1. 比如在编码阶段,我们不知道实例化的类名则:

     Class clazz = Class.forName("java.lang.String");
     clazz.newInstance();
    
  2. 比如我们在运行阶段,我们想访问Student这个类的私有属性name

     Student student = new Student();
     Class clazz = Student.class;
     Filed name = clazz.getDeclaredField("name");
     name.setAccessible(true);
     name.set("好人");
    

通过反射调用自身方法

    TestReflection c3 = new TestReflection();
    Method method = c1.getDeclaredMethod("info2", int.class);
    method.invoke(c3, 2);

方法:

public void info2(int a) {
    System.out.println(a);
    
}

测试结果:
2

利用反射修改私有属性

    package reflection;

import java.lang.reflect.Field;

public class TestStudent {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Student student = new Student();
        //获取Student的对象
        Class s = student.getClass();
        //获取id属性并为其赋值
        Field id = s.getDeclaredField("id");
        //将私有属性设为可见
        id.setAccessible(true);
        id.setInt(student, 10);
        //获取姓名
        Field name = s.getDeclaredField("name");
        name.setAccessible(true);
        name.set(student, "光头强");
        //获取male并为其赋值
        Field male = s.getDeclaredField("male");
        male.setAccessible(true);
        male.setBoolean(student, true);
        
        System.out.println("id:"+student.getId());
        System.out.println("name:"+student.getName());
        System.out.println("id:"+student.isMale());     
    }

}

测试结果:

id:10
name:光头强
id:true

利用反射创建对象

 package reflection;

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

public class TestStudent {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
            IllegalAccessException, NoSuchMethodException, InstantiationException, InvocationTargetException {

        Student student = new Student();
        Constructor c = student.getClass().getConstructor();
        // 第一种方法创建对象
        Student s = (Student) c.newInstance();
        // 第二种方法创建的对象
        Student s2 = student.getClass().newInstance();
        s.setId(10);
        s2.setId(20);
        System.out.println("id:" + s.getId());
        System.out.println("id:" + s2.getId());

    }

}

测试结果:

id:10
id:20

Class.newInstance()只能调用无参构造器,而且构造方法可见
Constructor.newInstance()可以调用有参构造器,在特定情况下调用不可见构造方法

利用反射创建可变数组

    package reflection;

import java.lang.reflect.Array;

public class TestStudent {
    
    public Object createArrayLength(Object array) {
        //获取数组对象,Class<?>为泛型
        Class<?> clazz = array.getClass();
        if(clazz.isArray()){
            //获取数组类型
            Class<?> componentType = clazz.getComponentType();
            //获取数组长度
            int length = Array.getLength(array);
            //创建新数组,并增加长度
            Object newArray = Array.newInstance(componentType, length+10);
            //将旧数组的数据复制给新数组
            System.arraycopy(array, 0, newArray, 0, length);
            return newArray;
        }
        return null;
    }
    
    public static void main(String[] args) {
        int[] array = new int[10];
        System.out.println("增加之前的数组长度:"+array.length);
        TestStudent ts = new TestStudent();
        int[] newArray = (int[]) ts.createArrayLength(array);
        System.out.println("增加之前的数组长度:"+newArray.length);

    }

}

测试结果:

增加之前的数组长度:10
增加之后的数组长度:20

注意:创建动态数组,可以使用ArrayUtils工具类,属于Commons Lang组件

链接知识点:泛型,Commons Lang组件

实例

题目:通过传入不同的字符串参数,使用反射来调用对应的方法

package reflection;

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

public class Animal {

    public void run() {
        System.out.println("动物会跑");
    }

    public void eat() {
        System.out.println("动物会吃");
    }

    public static void main(String[] args) {
        String name = "/run";
        String name2 = "/eat";
        //运用反射获取对象
        Animal animal = new Animal();
        Class clazz = Animal.class;
        //获取方法名
        String methodName = animal.getName(name);
        String methodName2 = animal.getName(name2);
        try {
            //运用反射获取方法
            Method method = clazz.getDeclaredMethod(methodName, null);
            Method method2 = clazz.getDeclaredMethod(methodName2, null);
            //运用反射调用相应方法
            method.invoke(animal, null);
            method2.invoke(animal, null);
        } catch (Exception e) {
            // TODO: handle exception
        }

    }
    
    /**
     * 去掉字符的多余部分,获取方法名
     * @param name
     * @return
     */
    public String getName(String name) {
        // 去掉字符串的“/”,并取出前后空格,返回方法名
        String methodName = name.substring(1).trim();
        return methodName;
    }

}

测试结果:

动物会跑
动物会吃

反射与动态代理

创建一个销售接口

package reflection;
public interface Seller {
    void sell();
}

创建一个实现接口的类BookSeller

package reflection;

public class BookSeller implements Seller {
    public void sell() {
        System.out.println("销售人员在卖书");
    }
}

创建一个代理商的类

package reflection;

import java.lang.reflect.InvocationHandler;

public class Agency implements InvocationHandler{
    public Object invoke(Object arg0, java.lang.reflect.Method arg1, 
        Object[] arg2) throws Throwable {
        System.out.println("代理人员在卖书");
        return null;    
    }
}

测试类

package reflection;

import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        Seller seller = new BookSeller();
        System.out.println("使用普通方法卖书");
        seller.sell();
        System.out.println("使用代理方法卖书");
        //获取类的加载器
        ClassLoader loader = Seller.class.getClassLoader();
        //指定代理的接口(Seller)和代理商(new Agency())
        seller = (Seller) Proxy.newProxyInstance(loader,new Class[]{Seller.class},new Agency());
        seller.sell();      
    }   
}

测试结果

使用普通方法卖书
销售人员在卖书
使用代理方法卖书
代理人员在卖房子

链接知识点:动态代理

相关文章

  • PHP Reflection 反射

    反射 ReflectionClass 类 PHP反射机制 反射在 PHP 中的应用

  • 反射的应用

    在内置函数中有讲到:反射说简单点 --> 就是利用字符串的形式去对象(模块)中操作(寻找/检查/删除/设置)成员。...

  • 反射的应用

    反射基础知识链接:http://www.jianshu.com/p/370073fad7e3 反射应用的场景 比如...

  • Java中的反射|SquirrelNote

    前言 本篇简介: 反射概述 反射具体功能实现 Android中的反射应用 一、反射(Reflection)概述 1...

  • reflect.go包学习_之二 指针操作提高反射性能 反射应用

    reflect.go包学习_之二 指针操作提高反射性能 反射应用 反射创建实例 反射信息、反射调用方法、反射修改值...

  • 安卓反射和动态代理的应用

    提纲 java反射基础 反射在Android中的应用 Java动态代理 动态代理在Android的应用 java反...

  • 反射原理以及反射的应用

    网上关于反射原理的有很多,首先讲一下反射的定义。定义:在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射的简单应用

    详见文章https://www.cnblogs.com/0xiasandu/p/11375980.html 1. ...

网友评论

    本文标题:反射的应用

    本文链接:https://www.haomeiwen.com/subject/vyxbattx.html