Java使用反射的通用数组复制方法
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使用反射的通用数组复制方法的更多相关文章
- Java -- 利用反射 操作任意数组,包括对象数组 和 基本数据类型的数组
items为任意数组
- java开发--反射技术
学习目标: 1.什么是反射:即反射的定义, 2.反射有什么作用,能解决什么问题, 3.反射的知识点是什么, 4.反射的利弊 5.反射的例子 1.什么是反射:反射的定义: a) 能够分析类能力的程序被称 ...
- 面试题思考:什么是 Java 的反射机制
一.反射机制概述 Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法.这种在运行时动态的获取信息以及动态调用对象的方法 ...
- 利用反射实现通用的excel导入导出
如果一个项目中存在多种信息的导入导出,为了简化代码,就需要用反射实现通用的excel导入导出 实例代码如下: 1.创建一个 Book类,并编写set和get方法 package com.bean; p ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- java的反射机制
一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...
- Java:反射
初识Java反射机制: 从上面的描述可以看出Java的反射机制使得Java语言可以在运行时去认识在编译时并不了解的类/对象的信息,并且能够调用相应的方法或修改属性的值.Java反射机制的核心就是允许在 ...
- Java数据结构和算法之数组与简单排序
一.数组于简单排序 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信 ...
- java笔记--反射进阶之总结与详解
一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是 ...
随机推荐
- Refit集成consul在asp.net core中的实践
前言 github:https://github.com/alphayu/ Refit.WebApiClient.Feign等都是支持声名式的Restful服务调用的开源组件. 这个几个组件都综合研究 ...
- Head First 设计模式 —— 00. 引子
Head First 学习原则 P xxx 可视化:图片使得学习效率更高,更易懂 交谈式:第一人称交谈方式讲述学习内容更易引起注意 多思考:自主思考练习题和拓展知识的问题 保持注意力集中:将知识融合进 ...
- 【剑指 Offer】07.重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 示例: 前序遍历 preorder = [3,9,20,15,7] 中序遍历 ...
- python3实现计算器
实验内容 1.简单计算器的设计 请设计简单的"加减乘除"计算器并从键盘上输入数据进行计算 数字的加减乘除,input返回的结果是str类型的,通过截取字符串中的运算符,来提取数字, ...
- 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs
题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...
- 十四:SQL注入之类型及提交注入
简要明确参数类型 数字,字符,搜索,json等 简要明确请求方法 GET,POST,COOKIE,REQUEST,HTTP头 其中SQL语句干扰符号:' " % ) } 等,具体查看用法 非 ...
- 【Linux】dd命令进行磁盘备份
运用dd命令,将/dev/sdb磁盘中所有的数据全部备份到/dev/sdc磁盘上,需要的命令如下 dd if=/dev/sdb of=/dev/sdc bs=1024k 说明,if是需要备份的磁盘 ...
- Upload - Labs (上)
Pass - 01: 1.尝试上传一个php文件:aaa.php,发现只允许上传某些图片类型,用bp抓包,发现http请求都没通过burp就弹出了不允许上传的提示框,这表明验证点在前端,而不在服务端 ...
- XSS - Pikachu
概述: Cross-Site Scripting 简称为"CSS",为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS.一般XSS可以分为如下几种常见类型 ...
- 使用jib-maven-plugin将Spring Boot项目发布为Docker镜像
目录 介绍 使用 总结 介绍 将spring boot(cloud)项目发布到docker环境作为镜像,一般常用的一个是com.spotify的docker-maven-plugin这个maven插件 ...