【问题标题】:String can't change. But int, char can change字符串不能改变。但是int、char可以改变
【发布时间】:2009-12-24 02:29:56
【问题描述】:

我读到在 Java 中,String 类型的对象不能改变。但是 int 和 char 变量可以。为什么?可以举个例子吗?

谢谢。 (我是新人-_-)

【问题讨论】:

  • 什么意思,不能改?你给我们举一个你所描述的例子怎么样?
  • 欢迎来到 SO。我认为您需要更具描述性才能获得建设性的答复。 :)
  • 我不明白为什么这些人会被否决。他是一个新手,只是问一个问题。通过给予否决票,您正在劝阻他。我看不出这个问题有什么问题,它是一个有效的问题!
  • 是的......这是一个完全合法和明智的问题。
  • Suraj Chandran 是一个伟人,Mark 也是。

标签: java string char int


【解决方案1】:

正如 bzabhi 所说,字符串在 Java 中是不可变的。这意味着字符串对象永远不会改变。这并不意味着您不能更改字符串变量,只是您不能更改字符串的底层内存表示。例如:

String str = "Hello";
str += " World!";

在这些行执行之后,str 将指向内存中的一个新字符串。原始的“Hello”字符串仍然存在于内存中,但很可能不会存在太久。假设没有情有可原的情况,任何东西都不会指向原始字符串,所以它将被垃圾收集。

我想最好的说法是,当示例的第 2 行执行时,内存中的一个新字符串是由原始字符串和添加到其中的字符串的连接创建的。 str 变量只是对内存位置的引用,然后更改为指向刚刚创建的新变量。

我对这一点并不是特别了解,但据我了解,这就是所有“非原始”值都会发生的情况。任何从 Object 派生的东西都遵循这些规则。原始值,例如 ints、bools、chars、float 和 doubles 允许更改内存中的实际值。所以,从这里:

int num = 5;
num += 2;

内存中的实际值发生变化。此代码示例不会创建新对象并更改引用,而是仅更改 num 变量在内存中的值。

至于为什么会这样,这只是Java制造商的设计决定。我相信有人会评论为什么会这样,但我不知道。

【讨论】:

  • 为什么?我只是在这里猜测,但这可能是因为如果你要扩展一个字符串,无论如何你都必须重新分配内存。字符是连续存储的,下面的字符可能无法使用,所以它只是重新分配了一块新的内存。
  • 即- 这种方式更有效(在大多数情况下)。除非您只想分配巨大的字符串以供潜在使用。但这就是 StringBuffer 的用途......
  • (我会比较 intInteger - 它们的行为方式非常相似。例如,AtomicIntegerStringBuilder 的行为与 Integer/int 完全不同和String。)
  • 为什么?想象一下,每次将其用作参数或返回时,都必须显式地制作一个副本。 C++ 隐式复制。尽管复制的内容取决于类型的类型。 Java 追求更简单的模型(至少对于程序员来说更容易,而不是高性能实现的实现者)。
  • 为什么不可变模型不是更容易实现高性能的模型?
【解决方案2】:

int 和 char 也不能改变。与字符串一样,您可以将不同的值放入同一个变量中,但整数本身不会改变。 3 永远是 3;您不能将其修改为 4。

【讨论】:

    【解决方案3】:

    String 是不可变类型(其中的值不能改变)。对于所有基本类型(boolean、byte、char、short、int、long、float 和 double)也是如此。

    int    x;
    String s;
    
    x = 1;
    x = 2;
    s = "hello";
    s = "world";
    x++; // x = x + 1;
    x--; // x = x - 1;
    

    如您所见,在任何情况下您都不能更改常量值(1、2、“hello”、“world”),但您可以更改它们指向的位置(如果您稍微扭曲一下思维并说int 变量指向一个常量 int 值)。

    【讨论】:

      【解决方案4】:

      我不确定是否可以(通过示例)显示字符串无法更改。但是您可以通过阅读Javadoc for the String class 的描述部分来确认这一点,然后阅读方法部分并注意没有可以更改字符串的方法。

      编辑:字符串在 Java 中被设计为不可变的原因有很多。最重要的原因是不可变字符串比可变字符串更容易正确使用。如果出于某种原因确实需要 String 的可变等效项,则可以使用 StringBuilder(或 StringBuffer)类。

      【讨论】:

        【解决方案5】:

        还值得注意的是,由于字符串是不可变的,因此如果将它们传递给方法,则不能在方法内部对其进行修改,然后在方法范围之外看到这些更改。

        public void changeIt(String s) {
            // I can't do anything to s here that changes the value 
            // original string object passed into this method
        } 
        
        public void changeIt(SomeObject o) {
            // if SomeObject is mutable, I can do things to it that will 
            // be visible outside of this method call
        } 
        

        【讨论】:

          【解决方案6】:

          这篇小文章可能比我能解释得更好:http://www.jchq.net/tutorial/09_02Tut.htm

          【讨论】:

            【解决方案7】:

            字符串在java 中是不可变的。尽管如此,您仍然可以将值附加或附加到字符串。我所说的值是指原始数据类型或其他字符串。

            但是,StringBuffer 是可变的,即它可以在内存中更改(不必分配新的内存块),这使得它非常高效。另外,请考虑以下示例:

            StringBuffer mystringbuffer = new StringBuffer(5000);
            
            for (int i = 0; i<=1000; i++)
            {
                mystringbuffer.append ( 'Number ' + i + '\n');
            }
            
            System.out.print (mystringbuffer);
            

            我们不是创建一千个字符串,而是创建一个可以扩展长度的对象 (mystringbuffer)。我们还可以设置一个推荐的起始大小(在本例中为 5000 字节),这意味着缓冲区不必在添加新字符串时不断请求内存。

            虽然StringBuffer 不会在所有情况下都提高效率,但如果您的应用程序使用长度增加的字符串,它会很有效。使用StringBuffers 也可以使代码更清晰,因为 append 方法使您不必使用冗长的赋值语句。

            【讨论】:

              猜你喜欢
              • 2013-01-08
              • 2012-06-09
              • 1970-01-01
              • 2022-11-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-05-03
              • 1970-01-01
              相关资源
              最近更新 更多