字符串是不可变的.究竟是什么意思? [英] String is immutable. What exactly is the meaning?

查看:24
本文介绍了字符串是不可变的.究竟是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在不可变字符串上编写了以下代码.

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",给我们值知识库".现在,由于 Strings 是不可变的,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 Strings 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"

发生了什么:

  1. 第一行非常简单:创建一个新的 String "java" 并将 s1 引用到它.
  2. 接下来,VM 创建另一个新的 String "java rules",但什么也没有指它.因此,第二个 String 立即丢失.我们达不到
  1. The first line is pretty straightforward: create a new String "java" and refer s1 to it.
  2. Next, the VM creates another new String "java rules", but nothing refers to it. So, the second String 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆