Java中的可变类与不可变类

可变类与不可变类

在学习软件构造课程时,一直对可变类与不可变类没有一个很清晰的认识,有些疑问,类似于:如果不可变类中是因为没有变值器才让他不可变的话,那么getter后得到的对象也是不可变类中的对象,那么获得之后不就是可以对其改变了吗,为什么不会影响不可变类中的对象呢?

要弄清这个问题,首先要理解可变数据类型与不可变数据类型

可变数据类型与不可变数据类型

可变数据类型:
对于一个可变数据类型的变量,当其值发生变化时,和原来的变量采用的是一个地址空间,即在原内存的基础上,对值进行的修改
不可变数据类型:
与可变数据类型相反,只要变量的值发生了改变,那么其地址空间也发生了变化,可以理解为将变量的“指针”指向了一个新的地址,这个新的地址里存储的就是新的值
下面是用图形来展示:
可变数据类型与不可变数据类型

可变类与不可变类

理解了可变数据类型与不可变数据类型后,再来看可变类与不可变类

根据上面的可变与不可变数据类型,我们又有了新的想法,可变类是没什么疑问了,对于不可变类中,如果采用了可变数据类型的变量和不可变类型数据的变量都利用getter获取他们的值,这样能否利用getter获得的值对其修改呢?下面是实际的尝试:

不可变类,可变数据类型变量:

public class unmutableADT {

	private StringBuffer str;
	
	public unmutableADT(StringBuffer str) {
		this.str = str;
	}
	
	public StringBuffer getter() {
		return this.str;
	}
	
}
public class tryness {

	public static void main(String[] args) {
		unmutableADT uta = new unmutableADT(new StringBuffer("AAA"));
		System.out.println(uta.getter());
		uta.getter().append("BBB");
		System.out.println(uta.getter());
		
	}
}
运行结果:
AAA
AAABBB

在这个例子中,利用的可变数据类型StringBuffer来进行测试,通过实验结果可以看出虽然unmutableADT中没有变值器,但是由于他的变量是可变数据类型,所以利用getter获得变量后即可利用其实可变数据类型的性质对其进行“隐秘的修改”

不可变类,不可变数据类型变量:

public class unmutableADT {

	private String str;
	
	public unmutableADT(String str) {
		this.str = str;
	}
	
	public String getter() {
		return this.str;
	}
	
}
public class tryness {

	public static void main(String[] args) {
		unmutableADT uta = new unmutableADT("AAA");
		System.out.println(uta.getter());
		uta.getter().concat("BBB");
		System.out.println(uta.getter());
	}
}
运行结果:
AAA
AAA

在这个例子中,同样是对getter到的变量进行了链接操作,但是由于String是不可变数据类型,所以无法对其进行在原地址空间内的修改,即修改后的新值并不在str指向的地址空间内,所以str仍然对应原来的值

主要的内容已经说完了,下面额外尝试一些奇怪的想法


在写不可变类时经常会发现final的字样,那么final到底起到什么作用呢,我做了一些尝试

尝试1
final可不可以限制可变数据类型同样不可被修改?

public class tryness {

	public static void main(String[] args) {
		
		final StringBuffer str = new StringBuffer("AAA");
		str.append("BBB");
		System.out.println(str);
		
	}
}
运行结果:
AAABBB

可见final不能阻止可变数据类型的修改

那么final到底限制了什么呢?

尝试2

public class tryness {

	public static void main(String[] args) {
		
		final String str;
		str = "AAA";
		str = "BBB";	//这行会报错
	}
}

对于final限制的变量,只允许赋值一次,后面再进行赋值会导致报错,这也就是为什么不可变类中的变量总是习惯上加一个final

我的理解是:final限制了地址空间不可变,所以根据可变和不可变数据类型变量的性质就导致上面这样的情况,这也就解决了我在之前做“软件构造Lab2”是的疑问,其中有一个类中就是用final修饰了一个list,当时我的理解没有现在这样清晰,总是认为final修饰了list,那么list是不是就不能在加入元素了呢,现在看来是不对的,list加元素时本身的地址空间没变,所以final也就不是对list元素不可变的制约。

此篇文章只是我个人理解,如果有错误欢迎指出,感谢阅读!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值