【问题标题】:Is toString() defined to return this for a java.lang.String?toString() 是否定义为为 java.lang.String 返回 this?
【发布时间】:2017-09-23 12:22:45
【问题描述】:

考虑

String foo = s.toString();

对于非null java.lang.String 实例s

这是定义为返回自身,还是取决于特定的 Java 实现?出于兴趣而采取“深拷贝”?

检查我的 JDK 源代码确认返回了 s,但 JLS 是否坚持这样做?我一直认为toString() 是任意序列化,可能代表对象,但不一定如此。例如,一个实现可以用引号字符包围字符串是完全合理的(至少在我看来)。

【问题讨论】:

  • toString() 返回 String 表示 ObjectString 比它自己更能代表 String Object 吗?
  • 的确,这是一种理性的思考方式,但语言规范不一定是理性的。
  • 你说的深拷贝是什么意思? toString 的行为在 JLS 中没有为 String 明确定义(但很明显,它应该返回自己)。然而,字符串内存操作是我希望在 JLS 或 JVM 规范中出现的东西......并且由于 String 是不可变的,所以制作任何副本都是没有意义的。
  • 请注意,它可能不在JLS的范围内,给出覆盖方法的实现细节。
  • @Berger:通常情况下,我同意这是 JRE 问题而不是 JLS 问题,但 JVMS 和 JLS do 都提到了java.lang.StringAFAIR,所以它可能在那里。 (我相信 JLS 也依赖于toString()。)

标签: java language-lawyer


【解决方案1】:

您不会在 JLS 中找到任何保证,但您在 the javadoc 中确实有一个:

这个对象(它已经是一个字符串!)本身被返回。

【讨论】:

  • 那么 JDK 就不能做其他事情了,比如将字符串括在引号中?
  • @P45Imminent 但是你为什么要这么做呢?
  • 因为这是合理的行为。不如按原样返回字符串合理,但仍然合理。
  • @P45Imminent 更新了我的答案。我的全部观点是没有充分的理由制作新副本。
  • @corsiKa 我相信他在质疑,给定字符串strstr==str.toString() 是否可能为假。
【解决方案2】:

它自己返回

 /**
     * This object (which is already a string!) is itself returned.
     *
     * @return  the string itself.
     */
    public String toString() {
        return this;
    }

查看source code,您可以轻松找到这一点。

我确信我们无法为每个方法的实现找到 Java 语言规范。就像 String 类的任何其他 Java 类 toString() 方法一样,它只返回它自己的字符串表示形式。

更新:

由于您的实际问题是关于为什么它返回它自己而不是复制或一些类似引号的黑客来创建一个新字符串,我对此略有不同意见。我这样做的原因(可能还有其他好的原因),因为您在实际字符串实例 (s) 本身上调用 toString() 方法,我认为这里没有什么害处。如果你想玩,无论如何你都可以直接使用s instance。

【讨论】:

  • 我确实这样做了,但 JLS 是否坚持
  • @ANS JavaDoc 保证每个 JDK 实现都必须遵守。源代码只是一个实现细节。 JavaDoc 是必须遵守的合同。顺便说一句,每一个软件都是如此。源代码只是一个可以(并且在大多数情况下可能会)改变一段时间的细节。
  • 对于Why it is returning it self rather than a copy or some hack like quotes to make a new String,我认为在String类中返回this是完全安全的,因为String对象是不可变的。
  • @ANS:哪个源代码?甲骨文的JDK? Oracle JRockit 的? IBM J9 JDK 的?冰茶的?阿帕奇和谐? GNU 类路径的? Excelsior JET?
  • 我不相信这能回答这个问题。 OP 明确表示他/她已经查看了 JDK 源代码并看到 toString 确实 返回 this,但问题是 JLS 是否需要它。
【解决方案3】:

是的。见Java Language Specification §1.4 – Relationship to Predefined Classes and Interfaces

如上所述,本规范通常引用 Java SE 平台 API 的类。特别是,某些类与 Java 编程语言有着特殊的关系。示例包括诸如ObjectClassClassLoaderStringThread 等类,以及包java.lang.reflect 中的类和接口等。本规范限制了此类类和接口的行为,但没有为它们提供完整的规范。 读者可参考 Java SE 平台 API 文档。

因此,这些类的 javadoc(即“Java SE 平台 API 文档”)是规范的,是整个语言规范的一部分。还有那个states explicitly

public String toString()

这个对象(它已经是一个字符串!)本身被返回。

没有解释的余地​​。

(如果他们改变它来做任何不同的事情,它会破坏无数的程序。)

【讨论】:

  • 这是(到目前为止)最好的答案,也是唯一一个完全解决这个问题的答案。重要的一点是,对于某些类的所需特性,JLS 遵循 Javadoc。
猜你喜欢
  • 2019-05-22
  • 2022-11-02
  • 2014-10-02
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
相关资源
最近更新 更多