在一次采访中,有人问我为什么String是不可变的
我是这样回答的:
当我们在java中创建一个字符串,如string s1="hello";然后一个
对象将在字符串池(hello)中创建,s1将
指着你好。现在如果我们再次执行String s2="hello";然后
不会创建另一个对象,但s2将指向hello
因为JVM将首先检查相同的对象是否在
是否为字符串池。如果不存在,则只创建一个新的,否则不存在。
现在如果假设java允许字符串可变,那么如果我们将s1改为hello world,那么s2值也将是hello world,所以java字符串是不可变的。
谁能告诉我我的答案是对的还是错的?
在Java中使字符串不可变的最重要的原因是安全考虑。下一个是缓存。
我相信这里给出的其他原因,比如效率、并发性、设计和字符串池,都源于字符串不可变的事实。如。可以创建字符串池,因为字符串是不可变的,而不是相反。
点击这里查看高斯林的采访记录
From a strategic point of view, they tend to more often be trouble free. And there are usually things you can do with immutables that you can't do with mutable things, such as cache the result. If you pass a string to a file open method, or if you pass a string to a constructor for a label in a user interface, in some APIs (like in lots of the Windows APIs) you pass in an array of characters. The receiver of that object really has to copy it, because they don't know anything about the storage lifetime of it. And they don't know what's happening to the object, whether it is being changed under their feet.
You end up getting almost forced to replicate the object because you don't know whether or not you get to own it. And one of the nice things about immutable objects is that the answer is, "Yeah, of course you do." Because the question of ownership, who has the right to change it, doesn't exist.
One of the things that forced Strings to be immutable was security. You have a file open method. You pass a String to it. And then it's doing all kind of authentication checks before it gets around to doing the OS call. If you manage to do something that effectively mutated the String, after the security check and before the OS call, then boom, you're in. But Strings are immutable, so that kind of attack doesn't work. That precise example is what really demanded that
Strings be immutable
从安全的角度来看,我们可以使用这个实际的例子:
DBCursor makeConnection(String IP,String PORT,String USER,String PASS,String TABLE) {
// if strings were mutable IP,PORT,USER,PASS can be changed by validate function
Boolean validated = validate(IP,PORT,USER,PASS);
// here we are not sure if IP, PORT, USER, PASS changed or not ??
if (validated) {
DBConnection conn = doConnection(IP,PORT,USER,PASS);
}
// rest of the code goes here ....
}