昨天学习了有关java的mutable和immutable的知识,在这里,凭借着记忆,写一篇较短的blog。
一:什么是mutable和immutable:
1. immutable指的是,一个变量在被分配了内存之后,他的值就不会被改变。例如:
int three = 3; 这句话的意思是指:在栈上开了一处内存,并将一个整数3放进了该处内存空间中,且该处内存空间的值在今后无法被修改。而mutable的变量则是相反,你可以在这个原本的内存中对数据进行修改,而不需要另外再开一处内存。
2.那么three = 4, 这又是什么意思呢?其实就和我上面说的那样,他是另外在栈中开了一处内存,并将一个4放入其内。在java中,每个你声明的变量,他本身就只是一个地址,或者说是一个管理者,真正的数据则是被放在了该处地址指向的内存空间中。所以,你无法改变immutable变量的对应内存里的内容,你可以做的是让这个immutable去管理其他的内存,从而实现的值的改变。
3.mutable的话就是指在一处管理的内存上进行修改。
一:什么是mutable和immutable:
1. immutable指的是,一个变量在被分配了内存之后,他的值就不会被改变。例如:
int three = 3; 这句话的意思是指:在栈上开了一处内存,并将一个整数3放进了该处内存空间中,且该处内存空间的值在今后无法被修改。而mutable的变量则是相反,你可以在这个原本的内存中对数据进行修改,而不需要另外再开一处内存。
2.那么three = 4, 这又是什么意思呢?其实就和我上面说的那样,他是另外在栈中开了一处内存,并将一个4放入其内。在java中,每个你声明的变量,他本身就只是一个地址,或者说是一个管理者,真正的数据则是被放在了该处地址指向的内存空间中。所以,你无法改变immutable变量的对应内存里的内容,你可以做的是让这个immutable去管理其他的内存,从而实现的值的改变。
3.mutable的话就是指在一处管理的内存上进行修改。
二.对象的mutable和immutable:
1.我们定义了一个对象,如果他的每个成员变量都是immutable的,且都无法被改变,那么我们就可以说这个对象是immutable的。我们来看如下的一份代码:
1.我们定义了一个对象,如果他的每个成员变量都是immutable的,且都无法被改变,那么我们就可以说这个对象是immutable的。我们来看如下的一份代码:
public class Message { private String name; private int ID; public Message(String name) { this.name = name; this.ID = name.hashCode(); } public String getName() { return name; } public int getID() { return ID; } }
分析一下这个类,我们发现除了在构造函数中队类的成员变量进行了一次初始化之后,成员对象就不会再被改变,因为通过observer返回的是immutable的变量,客户端无法直接对该内存的数值进行修改,我们的代码是安全的。
public class Person { private String firstname; private String lastname; private Date time; public Person(String firstname, String lastname, Date time) { this.firstname = firstname; this.lastname = lastname; this.time = time; } public String getFirstname() { return firstname; } public String getLastname() { return lastname; } public Date getTime() { return time; } }
这是一个很经典的例子,这里的成员变量有两个是immutable的还有一个Date类的对象是mutable的,这样我们的代码就是一个mutable的了,有了漏洞。当我们进行如下操作:
Instant now = Instant.now(); Person jim = new Person("Jim", "Smith", new Date(now.toEpochMilli())); System.out.println(jim.getTime()); Date danger = jim.getTime(); danger.setTime(now.toEpochMilli() + 3600000); System.out.println(jim.getTime());
这里我们实现建立了一个person类的对象,并用当前时刻的EpochMilli直取初始化这个Date,当我们Date类型的成员变量调用observer存入到danger中,对danger进行一个set操作时,我们发现,原对象的time成员变量中的内容被修改了。这就是mutable,我们也可以从中看出它的危害是巨大的。
mutable允许外界直接对当前返回回来的地址内的内容进行操作,危害极大,而immutable则禁止。
mutable允许外界直接对当前返回回来的地址内的内容进行操作,危害极大,而immutable则禁止。
三.final:
最后我们来区分一下final和immutable。从之前的介绍中我们得知了,immutable的变量的只能修改他管理的地址,而地址对应的内容无法修改。那么final是干什么的呢?其实很简单,被定义了final的变量,无法指向一个新的地址,他只能从一而终的对一处地址进行访问,如果是immutable的,那么他既然无法指向其他的地址,那么就无法指向其他的值。所以,final是对管理者的限制。
举个例子:
最后我们来区分一下final和immutable。从之前的介绍中我们得知了,immutable的变量的只能修改他管理的地址,而地址对应的内容无法修改。那么final是干什么的呢?其实很简单,被定义了final的变量,无法指向一个新的地址,他只能从一而终的对一处地址进行访问,如果是immutable的,那么他既然无法指向其他的地址,那么就无法指向其他的值。所以,final是对管理者的限制。
举个例子:
final List<String> people = new ArrayList<>();
对于上述的这么一个声明,由于List是mutable的,我们可以对他进行add,remove, sort…等等的操作,但是加了final之后,他就与一处内存绑定上了,这个时候,如果有以下的操作:
people = new ArrayList<>();
那么直接就会被静态类型检查报出error.