由于字符串是不可变的,我必须按如下方式编写,以从str中删除所有非字母数字。
void test(String str) {
str = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +str);
}
我无法理解的是,如何通过重新分配到str来实现它?
由于String是不可变的,我理解如果我将它分配给一个新的String newString,它们指出两个不同的对象str和newString。 它,原始字符串指向str和修改后的字符串指向ot newStr,它有两个不同的不可变字符串。这对我来说没问题。
void test(String str) {
String newStr = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +newStr);
}
但是如何重新分配到同一个str对象呢?根据我的理解,它不应该工作,因为不可变的str不能修改,所以修改的str的结果不能存储在不可变的str中。
void test(String str) {
// this shouldn't be working based on my understanding. But it works. Why?
str = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +str);
}
正如您所见,下面的图像中,string1和string2指向堆中的同一个String对象。你能澄清一下它在内部是如何运作的吗?
答案 0 :(得分:2)
您没有分配到同一个str对象。
看一下replaceAll等方法,你会看到它们返回String,这是一个替换所有方法创建的新String对象。
因此str=str.replaceAll()
从String
获取str
引用,在replaceAll()
中调用String
。 replaceAll
进程this
然后返回一个新的String
对象,其中包含该处理的结果。然后将其分配回原始参考。
答案 1 :(得分:2)
您需要了解参考:str
是对您记忆中某个区域的引用。发生了什么,Java运行时创建一个新的内存区域,其中包含删除所有字符的字符串,然后将“{1}”“指向”新的内存区域。
这与修改str
已指向的内存区域不同。
“Immutability”意味着变量指向的内存区域无法修改。内容是固定的。要“修改”它,必须复制,修改内存然后重新分配。
“Mutable”对象可以修改内存中的数据,而无需将旧数据复制到新的内存区域。
顺便说一句,在我们的示例中,字符串甚至被复制了两次!
第一次,复制字符串:
str
然后由
创建另一个副本replaceAll("[^a-zA-Z0-9\\s]", "")
然后最终分配给您的变量。
您的代码因此等于以下内容:
toLowerCase()
答案 2 :(得分:0)
您需要了解在Java中,变量不是对象;变量引用到对象。
因此,str
不是String
对象,它是对String
对象的引用。 “不可变”意味着变量所指的对象的内容不能改变;这并不意味着变量本身不能更改为引用不同的对象。
您正在使str
指向不同的String
对象;即String
返回的新str.replaceAll
对象。