Java中的可变数据与不可变数据

基本概念

不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。例如String
可变数据类型 :当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。例如StringBuilder

具体差别

当一个数据只有一个引用时,可变数据与不可变数据实际上并没有太大的差别。但是很明显真正的编程中一个数据经常会有多个引用,这是二者的区别就明显的变现出来了。先看两段段代码:

public static void main(String[] args) {
	    	String s1="1";
	    	String s2=s1;
	    	s2=s2+"2";
	    	System.out.println("s1:"+s1);
	    	System.out.println("s2:"+s2);
	    }

在这里插入图片描述

public static void main(String[] args) {
	    	StringBuilder s1=new StringBuilder("1");
	    	StringBuilder s2=s1;
	    	s2.append("2");
	    	System.out.println("s1:"+s1);
	    	System.out.println("s2:"+s2);
	    }

在这里插入图片描述
可以看出,当对String(不可变数据类型)进行更改时,对s2的更改不会影响s1.但当对StringBuilder(可变数据类型)进行更改时,对s2的更改会影响s1。原因就是对于不可变数据类型,更改它的值会让它指向一个新的地址空间。可变数据类型会直接更改原地址空间存储的内容,而此时s1和s2指向的还是同一片地址空间,因此s1的值也变了。具体用一张图很明显就能表现出来;
在这里插入图片描述
图和代码并不一致,但不影响理解

使用可变数据类型的风险以及解决方法

因为上述的特点,使用可变数据类型时会有一定风险。具体如下:

public static int sumAbsolute(List<Integer> list) {
		int sum=0;
	    for(int i = 0; i < list.size(); i++) 
	      list.set(i,Math.abs(list.get(i)));
	    for(Integer k:list) {
	    	sum=sum+k;
	    }
	    return sum;
	}

这里使用传入的list属于可变类型的数据,虽然达到了目的(求绝对值和),但也可能更改了List里面的值。但是Java在无特别说明时我们并不期望改变参数的值,因此有必要做出一定的措施,而这个措施就是防御性拷贝:

public static int sumAbsolute(List<Integer> list) {
		int sum=0;
		List<Integer> list1=new ArrayList<>(list);//防御式编程
	    for(int i = 0; i < list.size(); i++) 
	      list1.set(i,Math.abs(list.get(i)));
	    for(Integer k:list1) {
	    	sum=sum+k;
	    }
	    return sum;
	}
	 public static void main(String[] args) {
	    	List<Integer> l=new ArrayList<>();
	    	l.add(1);
	    	l.add(-1);
	    	l.add(-9);
	    	sumAbsolute(l);
	    	for(Integer i:l) {
	    		System.out.print(i+" ");
	    	}
	    }

结果如图:
在这里插入图片描述
在代码第三行,我们添加了一条语句:

List<Integer> list1=new ArrayList<>(list);

这里我们采用防御式编程重新获得了一个新的List对象用来替代参数中的list,这样一来就不用了担心list被方法修改了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值