Loading

30.3 Java进阶之使用反射编写数组CopyOf方法,调用任意方法

总结自《Java核心技术卷Ⅰ》

1.使用反射编写泛型数组代码

java.lang.reflect包中的Array类允许根据Class动态地创建数组。
比如Array类中的copyOf方法实现就是用了这个类,这个copyOf方法可以用于扩展一个已经填满的数组。

我们下面学习学习的是如何让一个特殊类型的数组转换成一个Object类型的数组的更加通用的copyOf方法。

实现这一目的我们需要用到的方法有:
在这里插入图片描述

1.1 学习例子

在这里插入图片描述

import java.lang.reflect.*;
import java.util.*;


public class CopyOfTest {

    public static void main(String[] args) {
        int[] a = { 1, 2, 3 };
        a = (int[]) goodCopyOf(a, 10);
        System.out.println(Arrays.toString(a));

        String[] b = { "Tom", "Dick", "Harry" };
        System.out.println("好的copyOf实现方式:");
        b = (String[]) goodCopyOf(b, 10);
        System.out.println(Arrays.toString(b));

        System.out.println("不好的copyOf实现方式访问数组:");
        Object[] bad = badCopyOf(b, 10);
        System.out.println(Arrays.toString(bad));
    }


    /**
     *  数组复制方法实现
     * (并不推荐这种做法,因为这样创建的是Object的数组,不能进行数组类型强转操作,也就是说每次取出元素使用都要进行强转)
     * @param a
     * @param newLength
     * @return
     */
    public static Object[] badCopyOf(Object[] a, int newLength){
        Object[] newArray = new Object[newLength];
        System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
        return newArray;
    }


    /**
     * 数组复制方法实现
     * 这种方式的好处是可以对数组类型进行强转的
     * @param a
     * @param newLength
     * @return
     */
    public static Object goodCopyOf(Object a, int newLength) {
        Class<?> cl = a.getClass();
        if (!cl.isArray()) return null;
        //获得数组元素类型
        Class<?> componentType = cl.getComponentType();
        int length = Array.getLength(a);//获得数组长度
        Object newArray = Array.newInstance(componentType, newLength);
        System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
        return newArray;
    }
}

2.使用反射调用任意方法

反射机制允许我们能不通过调用对象的方法调用对象中我们想要调用的方法。

在Method中有一个invoke的方法,它允许调用包装在当前Method对象中的方法。

2.1 例子

在这里插入图片描述

import java.lang.reflect.*;
public class MethodTableTest {

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

        //获取类MethodTableTest中定义的square(double x)方法对象
        Method square = MethodTableTest.class.getMethod("square", double.class);
        //获取类Math中定义的sqrt(double x)方法对象
        Method sqrt = Math.class.getMethod("sqrt", double.class);
        //通过反射执行
        printTable(1, 10, 10, square);
        printTable(1, 10, 10, sqrt);
    }


    /**
     * 定义计算一个数值的平方的方法
     * @param x
     * @return
     */
    public static double square(double x) {
        return x * x;
    }


    /**
     * 这个方法打印出区间 from-to 指定步长的值,并打印出其平方数
     * @param from 小边界值
     * @param to 大边界值
     * @param n 个数
     * @param f 方法对象
     */
    public static void printTable(double from, double to, int n, Method f) {
        //打印出Method所描述的方法
        System.out.println(f);
        //步长
        double dx = (to - from) / (n - 1);

        for (double x = from; x <= to; x += dx) {
            try {
                //执行Method所描述的方法
                double y = (Double) f.invoke(null, x);
                System.out.printf("%10.4f | %10.4f%n", x, y);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

3.代码仓库链接

Java基础学习/src/main/java/Progress/exa30_3 · 严家豆/Study - 码云 - 开源中国 (gitee.com)

posted @ 2020-05-12 14:02  文牧之  阅读(14)  评论(0)    收藏  举报  来源