美文网首页
JAVA反射

JAVA反射

作者: halfempty | 来源:发表于2018-11-13 20:35 被阅读0次

1 概述

白盒测试时,工具类最容易对付,直接调用类方法即可;public修饰的实例方法也还行,先实例化后调用;但是遇到private修饰的方法就头大了,虽然可以在类里写个main方法调用,但破坏了代码本身的完整性,功能代码与测试代码混在一起

不过,反射让我们彻底告别这个问题

2 基本成员

由class展开,类有构造函数(Constructor),类有成员变量(Field),类还有方法(Method)

然后使用public、private、protected、static、final等来修饰

当然还有注解,参数,返回值等,并且有相应的类型

所有这些,就像零件一样,组装成一个完整的class文件

反射正是将整个class拆散,来获取一个个零部件

3 简单API

测试样本

public class App {

    private static int COUNT = 0;
    public final int ONE = 1;

    public App() {
        COUNT++;
    }

    public int inc(int... nums) {
        return COUNT + ONE * nums.length;
    }

    @Deprecated
    public static int count() {
        return COUNT;
    }
}

3-1 Constructor

public class AppTest {

    static void log(String desc, Object ret) {
        System.out.println(String.format("%-20s : %s", desc, ret));
    }

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

        Class<App> clz = App.class;
        for (Constructor constructor : clz.getConstructors()) {
            log("getName", constructor.getName());
            log("getDeclaringClass", constructor.getDeclaringClass());
            log("getModifiers", constructor.getModifiers());
            log("getParameterCount", constructor.getParameterCount());
            log("getParameterTypes", Arrays.toString(constructor.getParameterTypes()));
        }

        App app = clz.getConstructor(null).newInstance(null);
        log("app.inc()", app.inc());
    }
}
--------------
getName              : App
getDeclaringClass    : class App
getModifiers         : 1
getParameterCount    : 0
getParameterTypes    : []
app.inc()            : 1

3-2 Method

public class AppTest {

    static void log(String desc, Object ret) {
        System.out.println(String.format("%-20s : %s", desc, ret));
    }

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

        Class<App> clz = App.class;
        for(Method method: clz.getDeclaredMethods()) {
            System.out.println(method.getName());
            log("\tgetModifiers", Modifier.toString(method.getModifiers()));
            log("\tgetParameterCount", method.getParameterCount());
            log("\tgetParameterTypes", Arrays.toString(method.getParameterTypes()));
            log("\tgetAnnotations", Arrays.toString(method.getAnnotations()));
            log("\tisVarArgs", method.isVarArgs());
        }

        Method m = clz.getDeclaredMethod("inc", int[].class);
        int[] param = {1, 2, 3};
        int result = (int)m.invoke(new App(), new Object[]{param});
        log("invoke inc", result);
    }
}public class AppTest {

    static void log(String desc, Object ret) {
        System.out.println(String.format("%-20s : %s", desc, ret));
    }

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

        Class<App> clz = App.class;
        for(Method method: clz.getDeclaredMethods()) {
            System.out.println(method.getName());
            log("\tgetModifiers", Modifier.toString(method.getModifiers()));
            log("\tgetParameterCount", method.getParameterCount());
            log("\tgetParameterTypes", Arrays.toString(method.getParameterTypes()));
            log("\tgetAnnotations", Arrays.toString(method.getAnnotations()));
            log("\tisVarArgs", method.isVarArgs());
        }

        Method m = clz.getDeclaredMethod("inc", int[].class);
        int[] param = {1, 2, 3};
        int result = (int)m.invoke(new App(), new Object[]{param});
        log("invoke inc", result);
    }
}
-----------
count
    getModifiers        : public static
    getParameterCount   : 0
    getParameterTypes   : []
    getAnnotations      : [@java.lang.Deprecated()]
    isVarArgs           : false
inc
    getModifiers        : public transient
    getParameterCount   : 1
    getParameterTypes   : [class [I]
    getAnnotations      : []
    isVarArgs           : true
invoke inc           : 4

3-3 Field

public class AppTest {

    static void log(String desc, Object ret) {
        System.out.println(String.format("%-20s : %s", desc, ret));
    }

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

        App app = new App();
        Class<App> clz = App.class;
        Field field = clz.getDeclaredField("ONE");
        log("getInt", field.getInt(app));
        log("getModifiers", Modifier.toString(field.getModifiers()));
    }
}
----------------
getInt               : 1
getModifiers         : public final

4 访问私有方法

  • 调用getDeclaredMethod获取方法,

  • 再使用setAccessible(true)使方法可访问

public class App {

   private void privateMethod() {
       System.out.println("private method");
   }
}

public class AppTest {

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

        App app = new App();
        Class<App> clz = App.class;

        Method method = clz.getDeclaredMethod("privateMethod");
        method.setAccessible(true);
        method.invoke(app);
    }
}

5 变参方法

  • 当变参类型为int时,invoke传入int[]可行
  • 当变参类型为String时,传入String[]却不行,需要用new Object[] {}包装
public class App {
    public void sum(int... nums) {
        int total = Arrays.stream(nums).sum();
        System.out.println(String.format("sum(%s) = %s", Arrays.toString(nums), total));
    }

    public void log(String... hobby) {
        System.out.println(String.format("Jack like %s", Arrays.toString(hobby)));
    }

    public static void main(String[] args) throws Exception {
        App app = new App();
        Class<App> clz = App.class;
        for(Method method: clz.getDeclaredMethods()) {
            if (method.getName().equals("sum")) {
                int[] nums = {1, 2, 3, 4, 5};
//                method.invoke(app, 1, 2, 3, 4, 5);    //error
                method.invoke(app, nums);

            } else if (method.getName().equals("log")) {
                String[] hobby = new String[] {"coding", "game", "girl"};
//                method.invoke(app, hobby);        //error
                method.invoke(app, new Object[]{hobby});
            }
        }
    }
}

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

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

  • 反射之二

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

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

      本文标题:JAVA反射

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