System.arraycopy()使用原理解析,坑点之:深拷贝和浅拷贝

一、深度复制和浅度复制的区别

         Java数组的复制操作可以分为深度复制和浅度复制,简单来说深度复制,可以将对象的值和对象的内容复制;浅复制是指对对象引用的复制。

二、System.arraycopy()方法实现复制

1、System中提供了一个native的静态方法arraycopy()。可以使用这个方法来实现数组之间的复制

  • 对于一维数组来说,这种复制属性值传递,修改副本 不会影响原来的值
  • 对于二维或者一维数组中存放的是对象时,复制结果是:一维的引用变量 传递给 副本的一维数组修改副本时,会影响原来的数组


2、System.arraycopy的函数原型是

     /*
     * @param      src      the source array.
     * @param      srcPos   starting position in the source array.
     * @param      dest     the destination array.
     * @param      destPos  starting position in the destination data.
     * @param      length   the number of array elements to be copied.
     * @exception  IndexOutOfBoundsException  if copying would cause
     *               access of data outside array bounds.
     * @exception  ArrayStoreException  if an element in the <code>src</code>
     *               array could not be stored into the <code>dest</code> array
     *               because of a type mismatch.
     * @exception  NullPointerException if either <code>src</code> or
     *               <code>dest</code> is <code>null</code>.
     */
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

其中:src表示源数组srcPos表示源数组要复制的起始位置destPos  目标数组的起始位置.desc表示目标数组length表示要复制的长度

 

3、利用System.arraycopy实现数组复制的示例:

package com.github.li.rpc.serialize.test;
/*System中提供了一个native方法arraycopy()*/

import java.util.stream.Stream;

public class SystemArrayCopy {

	public static void main(String[] args) {
		User[] users = new User[]{
				new User(1, "admin", "admin@qq.com"),
				new User(2, "maco", "maco@qq,com"),
				new User(3, "kitty", "kitty@qq,com")};//初始化对象数组
		User[] target = new User[users.length];//新建一个目标对象数组
		System.arraycopy(users, 0, target, 0, users.length);//实现复制

		System.out.println("源对象与目标对象的物理地址是否一样:" + (users[0] == target[0] ? "浅复制" : "深复制"));
		target[0].setEmail("admin@sina.com");
		System.out.println("修改目标对象的属性值后源对象users:");

		for (User user : users) {
			System.out.println(user);
		}
		//target[0] = new User();

		//一维数组
		Integer[] zz = new Integer[] {new Integer(1), new Integer(2), new Integer(3)};
		Integer[] tzz = new Integer[zz.length];
		System.arraycopy(zz, 0, tzz, 0, zz.length);
		System.out.println("深浅拷贝:" + (zz[0] == tzz[0] ? "浅拷贝" : "深拷贝"));
		tzz[0] = new Integer(1111);
		System.out.println("深浅拷贝:" + (zz[0] == tzz[0] ? "浅拷贝" : "深拷贝"));
		Stream.of(zz).forEach(i -> System.out.println(i));
		System.out.println(new Integer(1) == new Integer(5));

		int[] ss = new int[] {111, 222, 333};
		int[] tss = new int[ss.length];
		System.arraycopy(ss, 0, tss, 0, ss.length);
		tss[0] = 444;
		for (int s: ss) {
			System.out.println(s);
		}
	}

}
package com.github.li.rpc.serialize.test;
class User{
	private Integer id;
	private String username;
	private String email;
	//无参构造函数
	public User() {	}
	//有参的构造函数
	public User(Integer id, String username, String email) {
		super();
		this.id = id;
		this.username = username;
		this.email = email;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", email=" + email
				+ "]";
	}
}

 

  1. 程序运行的结果:

下图是System.arraycopy()复制的过程:

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`System.arraycopy()`方法是将原数组中的数据复制到目标数组中,对于基本数据类型,确实是深拷贝(即复制了原数组中的数据到目标数组中)。但是对于引用类型,`System.arraycopy()`方法只是复制了引用而已,也就是说,复制后的目标数组中的元素和原数组中的元素指向的是同一个对象。因此,对于引用类型,`System.arraycopy()`方法只是浅拷贝。 举个例子,假设我们有一个原数组`orig`和一个目标数组`dest`,其中`orig`数组中的元素是一个引用类型的对象。如果我们使用`System.arraycopy()`方法将`orig`复制到`dest`中,那么`dest`中的元素和`orig`中的元素指向的是同一个对象。如果我们修改了`dest`中的元素,那么`orig`中的元素也会受到影响。 ```java class MyClass { int value; public MyClass(int value) { this.value = value; } } MyClass[] orig = new MyClass[] { new MyClass(1), new MyClass(2), new MyClass(3) }; MyClass[] dest = new MyClass[3]; System.arraycopy(orig, 0, dest, 0, 3); // 修改dest中的元素 dest[0].value = 100; // 输出orig中的元素 System.out.println(orig[0].value); // 输出100 ``` 在上面的例子中,我们将`orig`复制到`dest`中,然后修改了`dest`中的第一个元素。最后输出`orig`中的第一个元素,发现它的值也变成了100。这是因为`orig`中的元素和`dest`中的元素指向的是同一个对象,所以修改`dest`中的元素也会影响到`orig`中的元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值