Java版顺序表的浅拷贝与深拷贝(二)

Java版顺序表的浅拷贝与深拷贝(二)

Java版顺序表的浅拷贝与深拷贝(一)

  当一个类包含数组或对象等引用类型的成员变量时,该类声明的拷贝构造方法,不仅要复制基本类型的成员变量的值,还要为引用类型变量申请存储空间,并复制其中所有对象,这种复制方式称为深拷贝

  SeqList<T> 类声明深拷贝构造方法如下,申请数组存储空间复制所有数组元素。

public SeqList(SeqList<T> list) {//深拷贝构造方法,复制list
		this.n = list.n;
		this.element = new Object[list.element.length];//申请一个数组空间
		for (int i = 0; i < list.n; i++) {//复制数组中所有元素
			this.element[i] = list.element[i];
		}

	}
  SeqList<T>深拷贝执行结果如下图(a),listb.element申请新的数组空间,使得lista.element与listb.element分别引用各自的数组。

  SeqList深拷贝之后,lista和listb拥有自己的element数组空间,进行插入和删除操作时互不影响,但是,因为对象赋值是引用赋值,深拷贝只是对数组进行了空间申请,对于数组中的对象元素并没有申请新的空间,所以导致lista.element和listb.element两个数组对应元素引用相同实例,如果进行修改操作,仍会影响对方。执行下面代码查看运行结果

public static void main(String[] args) {
		int n = 5;
		SeqList<StringBuilder> lista = new SeqList<StringBuilder>(n - 1);
		for (int i = 0; i < n; i++) {
			lista.insert(new StringBuilder(((char)('A' + i) + "")));// 尾插入
		}
		SeqList<StringBuilder> listb = new SeqList<StringBuilder>(lista);// 执行拷贝构造方法
		System.out.println("图(a), lista = " + lista.toString());
		System.out.println("       listb = " + listb.toString());

		lista.insert(new StringBuilder("F"));//lista在最后插入一个元素F
		listb.remove(listb.n - 1);//listb删除最后一个元素
		StringBuilder strBud = lista.get(0);
		strBud.setCharAt(0, 'X');//lista修改第一个元素为X
		System.out.println("图(b), lista = " + lista.toString());
		System.out.println("       listb = " + listb.toString());

	}

对应的内存空间变化如下图:


  所以,深拷贝应该是,复制每个引用类型成员变量所引用的数组或对象,直至该对象可达的所有对象,

如图上图(c)所示。

完整的运行程序代码如下:

public class SeqList<T> {

	private int n;
	private Object[] element;

	/**
	 * 构造长度为length的空表
	 */
	public SeqList(int length) {
		this.element = new Object[length];
		this.n = 0;
	}
	 
	public SeqList(SeqList<T> list) {// 深拷贝构造方法,复制list
		this.n = list.n;
		this.element = new Object[list.element.length];// 申请一个数组空间
		for (int i = 0; i < list.n; i++) {// 复制数组中所有元素
			this.element[i] = list.element[i];
		}
	}

	/**
	 *获取一个元素
	 */
	public T get(int i) {
		if (i >= 0 && i < this.n) {
			return (T) this.element[i];
		}
		return null;
	}

	/**
	 * 插入一个元素
	 */
	public void set(int i, T x) {
		if (x == null) {
			throw new NullPointerException("x==null");
		}
		if (i >= 0 && i < this.n) {
			this.element[i] = x;
		} else {
			throw new IndexOutOfBoundsException();
		}
	}

	/**
	 * 插入一个数据元素
	 */
	public void insert(T x) {
		Object[] source = this.element;
		if (this.n == element.length) {
			this.element = new Object[element.length * 2];
			for (int i = 0; i < source.length; i++) {
				this.element[i] = source[i];
			}
		}
		this.element[this.n] = x;
		this.n++;

	}

	/**
	 * @param i
	 *            删除第i个元素
	 */
	public T remove(int i) {
		if (this.n > 0 && i >= 0 && i < this.n) {

			T old = (T) this.element[i];
			for (int j = i; j < this.n - 1; j++) {
				this.element[j] = this.element[j + 1];// 从i+1开始向前移动一个位置
			}
			this.element[this.n - 1] = null;
			this.n--;
			return old;
		}
		return null;
	}

	/**
	 * 返回顺序表所有元素的数据
	 */
	public String toString() {
		String str = "";
		if (this.n > 0) {
			str = this.element[0].toString();
			for (int i = 1; i < this.n; i++) {
				str += "," + this.element[i].toString();
			}
		}
		return str;
	}

	public static void main(String[] args) {
		int n = 5;
		SeqList<StringBuilder> lista = new SeqList<StringBuilder>(n - 1);
		for (int i = 0; i < n; i++) {
			lista.insert(new StringBuilder(((char)('A' + i) + "")));// 尾插入
		}
		SeqList<StringBuilder> listb = new SeqList<StringBuilder>(lista);// 执行拷贝构造方法
		System.out.println("图(a), lista = " + lista.toString());
		System.out.println("       listb = " + listb.toString());

		lista.insert(new StringBuilder("F"));//lista在最后插入一个元素F
		listb.remove(listb.n - 1);//listb删除最后一个元素
		StringBuilder strBud = lista.get(0);
		strBud.setCharAt(0, 'X');//lista修改第一个元素为X
		System.out.println("图(b), lista = " + lista.toString());
		System.out.println("       listb = " + listb.toString());

	}
}

运行结果如下:

图(a), lista = A,B,C,D,E
       listb = A,B,C,D,E
图(b), lista = X,B,C,D,E,F
       listb = X,B,C,D






  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值