字符串是不可变的.究竟是什么意思? [英] String is immutable. What exactly is the meaning?
问题描述
我在不可变字符串上编写了以下代码.
I wrote the following code on immutable Strings.
public class ImmutableStrings {
public static void main(String[] args) {
testmethod();
}
private static void testmethod() {
String a = "a";
System.out.println("a 1-->" + a);
a = "ty";
System.out.println("a 2-->" + a);
}
}
输出:
a 1-->a
a 2-->ty
这里变量a
的值被改变了(虽然很多人说不可变对象的内容不能改变).但是,String
是不可变的究竟是什么意思?你能帮我澄清一下这个话题吗?
Here the value of variable a
has been changed (while many say that contents of the immutable objects cannot be changed). But what exactly does one mean by saying String
is immutable? Could you please clarify this topic for me?
来源:https://docs.oracle.com/javase/教程/java/nutsandbolts/datatypes.html
推荐答案
在进一步讨论 不变性 之前,让我们先看看 String
类和在得出任何结论之前先了解一下它的功能.
Before proceeding further with the fuss of immutability, let's just take a look into the String
class and its functionality a little before coming to any conclusion.
String
是这样工作的:
String str = "knowledge";
像往常一样,这会创建一个包含 "knowledge"
的字符串,并为其分配一个引用 str
.够简单吗?让我们执行更多功能:
This, as usual, creates a string containing "knowledge"
and assigns it a reference str
. Simple enough? Lets perform some more functions:
String s = str; // assigns a new reference to the same string "knowledge"
让我们看看下面的语句是如何工作的:
Lets see how the below statement works:
str = str.concat(" base");
这会将字符串 " base"
附加到 str
.但是等等,这怎么可能,因为 String
对象是不可变的?出乎你的意料,它是.
This appends a string " base"
to str
. But wait, how is this possible, since String
objects are immutable? Well to your surprise, it is.
执行上述语句时,VM取String str
的值,即"knowledge"
并附加" base"
,给我们值知识库"
.现在,由于 String
s 是不可变的,VM 不能将这个值分配给 str
,所以它创建了一个新的 String
对象,给它一个值知识库"
,并给它一个引用str
.
When the above statement is executed, the VM takes the value of String str
, i.e. "knowledge"
and appends " base"
, giving us the value "knowledge base"
. Now, since String
s are immutable, the VM can't assign this value to str
, so it creates a new String
object, gives it a value "knowledge base"
, and gives it a reference str
.
这里需要注意的重要一点是,虽然 String
对象是不可变的,它的引用变量不是. 所以这就是为什么在上面的例子中,引用被用来引用一个新形成的 String
对象.
An important point to note here is that, while the String
object is immutable, its reference variable is not. So that's why, in the above example, the reference was made to refer to a newly formed String
object.
此时在上面的例子中,我们有两个 String
对象:第一个我们创建的值为 "knowledge"
,由 s<指向/code>,第二个
知识库"
,由str
指向.但是,从技术上讲,我们有三个 String
对象,第三个是 concat
语句中的文字 "base"
.
At this point in the example above, we have two String
objects: the first one we created with value "knowledge"
, pointed to by s
, and the second one "knowledge base"
, pointed to by str
. But, technically, we have three String
objects, the third one being the literal "base"
in the concat
statement.
如果我们没有另一个引用 s
到 "knowledge"
怎么办?我们会丢失那个 String
.但是,它仍然会存在,但会因没有引用而被视为丢失.再看下面的一个例子
What if we didn't have another reference s
to "knowledge"
? We would have lost that String
. However, it still would have existed, but would be considered lost due to having no references.
Look at one more example below
String s1 = "java";
s1.concat(" rules");
System.out.println("s1 refers to "+s1); // Yes, s1 still refers to "java"
发生了什么:
- 第一行非常简单:创建一个新的
String
"java"
并将s1
引用到它. - 接下来,VM 创建另一个新的
String
"java rules"
,但什么也没有指它.因此,第二个String
立即丢失.我们达不到
- The first line is pretty straightforward: create a new
String
"java"
and refers1
to it. - Next, the VM creates another new
String
"java rules"
, but nothing refers to it. So, the secondString
is instantly lost. We can't reach it.
引用变量s1
仍然引用原来的String
"java"
.
The reference variable s1
still refers to the original String
"java"
.
几乎所有应用于 String
对象以修改它的方法,都会创建新的 String
对象.那么,这些 String
对象去哪里了?嗯,这些都存在于内存中,任何编程语言的主要目标之一就是有效利用内存.
Almost every method, applied to a String
object in order to modify it, creates new String
object. So, where do these String
objects go? Well, these exist in memory, and one of the key goals of any programming language is to make efficient use of memory.
随着应用程序的增长,String
文字占用大量内存是很常见的,这甚至会导致冗余.所以,为了让 Java 更高效,JVM 留出了一个特殊的内存区域,称为字符串常量池".
As applications grow, it's very common for String
literals to occupy large area of memory, which can even cause redundancy. So, in order to make Java more efficient, the JVM sets aside a special area of memory called the "String constant pool".
当编译器看到 String
文字时,它会在池中查找 String
.如果找到匹配项,则对新文字的引用将指向现有的 String
,并且不会创建新的 String
对象.现有的 String
只是多了一个引用.这里是使 String
对象不可变的重点:
When the compiler sees a String
literal, it looks for the String
in the pool. If a match is found, the reference to the new literal is directed to the existing String
and no new String
object is created. The existing String
simply has one more reference. Here comes the point of making String
objects immutable:
在String
常量池中,一个String
对象可能有一个或多个引用.如果多个引用指向同一个String
,甚至都不知道,如果其中一个引用修改了那个String
值,那将会很糟糕.这就是为什么 String
对象是不可变的.
In the String
constant pool, a String
object is likely to have one or many references. If several references point to same String
without even knowing it, it would be bad if one of the references modified that String
value. That's why String
objects are immutable.
好吧,现在你可以说,如果有人覆盖了 String
类的功能会怎样?这就是 String
的原因类被标记为 final
以便没有人可以覆盖其方法的行为.
Well, now you could say, what if someone overrides the functionality of String
class? That's the reason that the String
class is marked final
so that nobody can override the behavior of its methods.
这篇关于字符串是不可变的.究竟是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!