【问题标题】:what the objects of string class are final and is there any object that is final什么字符串类的对象是最终的,是否有任何对象是最终的
【发布时间】:2014-03-11 22:14:31
【问题描述】:

在 SCJP 书中,我得到 Kathy Sierra 的观点,即它们不是 java 中的最终对象。 java中只有final引用变量。

但我认为字符串类的对象是最终的。一旦初始化,它们的状态就不能改变。

现在的问题是字符串类的对象是否是最终的。 如果它们不是字符串类的对象是不可变的。

谢谢

【问题讨论】:

  • 我想重点是,如果你有 aA 的变量,你不能使 a 成为最终的(至少在 C++ 中不能通过 const 实现),除非类 A 允许它(例如,它有 makeImutable() 方法或其他东西,这将不允许进一步更改)。阅读更多:stackoverflow.com/questions/4971286/javas-final-vs-cs-const

标签: java string


【解决方案1】:

但我认为字符串类的对象是最终的。一旦初始化,它们的状态就不能改变。

不,它们不是 Java 意义上的 final。它们是不可变的,但final 纯粹与变量/数据成员相关,而不是对象。

这是一个例子:

final String a = "foo";
String b = "bar";

b = "updated bar"; // Compiles and works, `b` (the variable) can be changed
a = "updated foo"; // Won't compile, you're not allowed to change the `a` variable

final 是关于“变量”的值是否可以改变,而不是关于对象的状态是否可以改变。

这是一个示例,其中 final 变量引用了一个可变对象:

final Map a = new HashMap();

a.add("foo", "bar"); // Works; we're not changing `a`, we're changing the state
                     // of the object `a` refers to

只是为了完全取出物体:

final int a = 5;
a = 6; // Won't compile, because we aren't allowed to change `a`

【讨论】:

  • 但是如何改变字符串类本身的“foo”对象的内容。 “foo”字符串如何保持不可变。我认为它可能应该是最终的。
  • @D.k.Agrawal: “但是如何改变字符串类本身的“foo”对象的内容。” “对象”(或“实例”),而不是“类” ;而你不能。 “如何“foo”字符串保持不可变。我认为它应该是最终的。” 它是不可变的,因为在String 上没有可用的操作来改变对象的状态。这与引用对象的变量是否可以更新为引用新对象无关。
  • (其实你可以通过反射改变一个String,但是这样做是邪恶的。)
  • @DavidConrad - 任何对象都可以这样更改。但是我们在讨论不变性时没有考虑到这一点,因为使用反射来打破抽象是 JLS 所说的 Java 语言之外的一个领域。行为未指定。 (也可以使用Unsafe 或 JNI/JNA 调用来做同样的事情。)
  • @DavidConrad - 我看到并理解了括号。但我怀疑其他人可能无法理解其中的微妙之处。 (事实上​​,我记得以前的问题,人们错误地认为邪恶的反射后门使 String 可变!)
【解决方案2】:

首先你必须阅读:

http://en.wikipedia.org/wiki/Final_(Java)

因为在 Java 中 final 关键字可以在几种不同的上下文中使用。

String类是不可变的,也就是说这个对象创建后的状态是不能改变的,同时也声明为final,不能被子类化。

【讨论】:

  • yaaa jakub 我已经读过了。字符串类对象如何不可变。表示 JVM 实际执行的操作以保持 String 对象不可变
【解决方案3】:

您必须发布章节(顺便说一下,请不要)以完整地给出上下文,但我可以为您进一步区分这两个概念。

final 是 java 中的一个关键字,在您的情况下,它适用于引用变量。这意味着一旦对象被实例化,该变量就不能被分配给不同的对象,即,如果你这样做:

final String[] stringArray = new String[8];

你再也不能这样了:

stringArray = new String[2];//stringArray is final and cannot be reassigned

但这并不表示 stringArray 的内容是否无法更改。你可以这样做:

stringArray[3] = "Hey!";

它会编译得很好。这向您表明,不能仅将引用重新分配给其他任何东西;我们在这里只讨论参考。

当他们说 String 是不可变的时,他们是在谈论 String 常量池。在字符串常量池中,有一组在内存中创建的字符串,这些字符串被存储起来以供重用。如果你说,例如:

String tempString1 = "yo";
String tempString2 = "yo";

您仅在字符串常量池(字符串所在的内存的特殊部分)中创建了 1 个字符串对象,并将其分配给两个不同的引用变量。如果你这样做:

tempString2 = "hey";
String tempString3 = "yo";

你只在字符串常量池中再次创建了 1 个新对象,“嘿”。 tempString1 只更改了它指向的内容,而 tempString3 正在重用已经创建的“yo”。

如果你这样做是因为你对 Java 很着迷:

tempString1 = tempString2 + tempString3;
String tempString4 = tempString2 + tempString3;
String tempString5 = tempString2 + tempString3;

您只创建了 1 个字符串“heyyo”。 "yo" "hey" 和 "heyyo" 是字符串常量池中唯一的字符串。

您所做的任何操作都不会更改字符串常量池中的“hey”和“yo”,即使您可能会更改输出以使这些字符串看起来已更改。

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多