Java通用数组复制方法

在Arrays工具类中,提供了一个copyOf(T[] original, int newLength)方法,用于复制任意类型的对象数组,但是由于泛型不能作用于基本类型,所以Arrays工具类中又额外提供了处理基本数据类型数组的函数,但是使用反射可以讲这些方法都统一起来。

为了对比,先来看一个实现的不太好的数组拷贝的例子:

public static Object[] badCopy(Object[] objects, int newLength) {
Object[] des = new Object[newLength];
System.arraycopy(objects, 0, des, 0, Math.min(newLength, objects.length));
return des;
}

这个方法copy方法在很多情况下也能正常工作,但是存在很多问题。

首先,只能拷贝对象数组。因为传递的参数是Object[],所以难以扩展到基本类型;

其次,由于使用Object[]声明新数组,所以没法将返回结果转换为想要拷贝的实际类型。比如想拷贝的是Person对象的数组,但是这里的返回值是一个Object的数组,而且还无法转换成。在Java中,如果一开始声明的是Object对象,将它临时转换到Object,然后再转回来是可以的,但是如果一开始就声明了Object,就无法向下转型了,Java会记住声明时的类型信息,也就是一个对象的静态类型信息。

为了解决以上问题,使用如下的方法:

public static Object copyOf(Object arr, int newLength) {
Class cl = arr.getClass();
// 如果不是数组 返回
if (!cl.isArray()) return null;
// 获取数组中元素的类型
Class componentType = cl.getComponentType();
// 创建新数组实例
Object res = Array.newInstance(componentType, newLength);
System.arraycopy(arr, 0, res, 0, Math.min(newLength, Array.getLength(arr)));
return res;
}

该方法接受Object对象作为参数,所以可以处理基本类型,因为数组总是一个对象,对象类型的数组是一个数组对象,基本类型的数组同样是数组对象,所以可以正确的传递参数;

再看内部实现中,获取数组的类对象,然后再使用获取数组中元素的类型,用这个类型来创建新的数组,这就保证了最终可以将结果向下转型为想要的类型;返回的类型是Object,通过上述描述可知,得到结果后,只要手动的转换成想要的类型即可。

public static void main(String[] args) {
int[] a = new int[]{1, 2, 3, 4};
int[] b = (int[]) CopyArray.copyOf(a, 3);
System.out.println(Arrays.toString(b)); String[] c = new String[]{"xx", "yy", "zz"};
String[] d = (String[]) CopyArray.copyOf(c, 10);
System.out.println(Arrays.toString(d));
}

这个方法虽然可以将所有类型数组的拷贝统一,但是不好的地方在于需要手动进行类型转换,而Arrays工具类中,虽然没有统一所有方法,但是使用重载将让用户可以更方便的使用,而不需要类型转换。

或许这就是通用和专用的权衡吧。

Java使用反射的通用数组复制方法的更多相关文章

  1. Java -- 利用反射 操作任意数组,包括对象数组 和 基本数据类型的数组

    items为任意数组

  2. java开发--反射技术

    学习目标: 1.什么是反射:即反射的定义, 2.反射有什么作用,能解决什么问题, 3.反射的知识点是什么, 4.反射的利弊 5.反射的例子 1.什么是反射:反射的定义: a) 能够分析类能力的程序被称 ...

  3. 面试题思考:什么是 Java 的反射机制

    一.反射机制概述 Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法.这种在运行时动态的获取信息以及动态调用对象的方法 ...

  4. 利用反射实现通用的excel导入导出

    如果一个项目中存在多种信息的导入导出,为了简化代码,就需要用反射实现通用的excel导入导出 实例代码如下: 1.创建一个 Book类,并编写set和get方法 package com.bean; p ...

  5. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  6. java的反射机制

    一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

  7. Java:反射

    初识Java反射机制: 从上面的描述可以看出Java的反射机制使得Java语言可以在运行时去认识在编译时并不了解的类/对象的信息,并且能够调用相应的方法或修改属性的值.Java反射机制的核心就是允许在 ...

  8. Java数据结构和算法之数组与简单排序

    一.数组于简单排序 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信 ...

  9. java笔记--反射进阶之总结与详解

    一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是 ...

随机推荐

  1. spring boot 集成 Apache CXF 调用 .NET 服务端 WebService

    1. pom.xml加入 cxf 的依赖 <dependency> <groupId>org.apache.cxf</groupId> <artifactId ...

  2. DRF之访问权限控制和访问频率控制(节流)

    权限控制 前言 用户验证用户权限,根据不同访问权限控制对不同内容的访问. 建议了解视图.token验证的内容. 使用流程 自定义访问权限类,继承BasePermission,重写has_permiss ...

  3. 2.2.2 Sqoop2 基本架构

    主要组件 1.Sqoop Client 定义了用户使用Sqoop的方式,包括客户端命令行CLI和浏览器两种方式,浏览器允许用户直接通过Http方式完成Sqoop的管理和数据的导出 2.Sqoop Se ...

  4. Linux sed 命令总结

    一.sed格式命令 sed 命令行格式为:sed [选项] 'command' 输入文本 二.sed命令的选项 sed [选项] [动作] 选项与参数: -n :使用安静(silent)模式.在一般 ...

  5. linux下如何看系统日志及Out Of Memery

    1.一个Out Of Memery(OOM)导致的崩溃. linux系统经常会由于资源的问题导致自己的程序莫名被杀掉,可以从linux的系统日志中找到答案: vi /var/log/message - ...

  6. #2使用html+css+js制作网站教程 测试

    #2使用html+css+js制作网站教程 测试 本系列链接 1 测试 1.1 运行 1.2 审查 1.3 审查技巧 1.4 其他 引言: 编写完代码后就要上机测试代码,获得用户体验,筛选bug 笔者 ...

  7. ICPC Central Russia Regional Contest (CRRC 19)题解

    题目连接:https://codeforces.com/gym/102780 寒假第二次训练赛,(某菜依旧是4个小时后咕咕咕),战况还行,个人表现极差(高级演员) A:Green tea 暴力枚举即可 ...

  8. XSS-labs通关挑战(xss challenge)

    XSS-labs通关挑战(xss challenge) 0x00 xss-labs   最近在看xss,今天也就来做一下xss-labs通过挑战.找了好久的源码,终于被我给找到了,因为在GitHub上 ...

  9. Docker学习笔记之基本命令使用

    测试的环境为Ubuntu1804. 1. search命令搜索镜像 sudo docker search centos 搜索centos相关的镜像,可以看到第一个最多星的的centos是官方的镜像,而 ...

  10. MySQL select 子查询的使用

    ### 子查询 >where 这个值是计算出来的 >本质:`在 where 语句中嵌套一个子查询语句` ```sql /*============== 子查询 ============== ...