跨Java虚拟机实现的Java toString表示?

跨Java虚拟机实现的Java toString表示?,java,jvm,Java,Jvm,对于大多数核心库和Java类,“toString”表示是所有Java实现的标准表示。或者这在Java规范中没有指定 例如,如果我这样做了,那么new HashMap()/toString就是来自OpenJDK的输出,预期与IBM jrockit相同 它们应该兼容吗?如果您正在将代码从一个JVM移植到另一个JVM,并且希望字符串表示形式相同,则可能会出现问题。只是不要期望[toString()方法]的字符串输出相同。没有指定方法的内容和格式(查看相关的javaDoc) 甚至不能保证来自同一供应商的

对于大多数核心库和Java类,“toString”表示是所有Java实现的标准表示。或者这在Java规范中没有指定

例如,如果我这样做了,那么new HashMap()/toString就是来自OpenJDK的输出,预期与IBM jrockit相同

它们应该兼容吗?如果您正在将代码从一个JVM移植到另一个JVM,并且希望字符串表示形式相同,则可能会出现问题。

只是不要期望[toString()方法]的字符串输出相同。没有指定方法的内容和格式(查看相关的javaDoc)


甚至不能保证来自同一供应商的不同版本的实现是相同的。因此,永远不要根据
toString()
的结果比较实例,也不要将这些结果用作数据库中的键或标识符。它们只是实例的文本表示。没什么了。

好问题,我想说这取决于实现。没有正式的规范存在。尽管像这样的书清楚地说明了图书馆将做什么,但并不一定说“应该做”

因此,实现者可以自由选择和记录
toString()
显示的内容,但不能保证在其他JVM实现中显示的内容是相同的

要解决您的问题,确保
toString()
实现的唯一方法是
@在派生类中重写
公共字符串toString()
方法(是的,您必须派生您想要的每个类
toString()
),并显式指定其输出。

说明:

1.4。与预定义类和接口的关系

如上所述,该规范通常引用Java类 SE平台API。特别是,有些类有特殊的功能 与Java编程语言的关系。例子包括 类,如对象、类、类装入器、字符串、线程和 包java.lang.reflect中的类和接口等。 此规范约束此类类和类的行为 接口,但未为其提供完整的规范。 读者可以参考JavaSE平台API文档


所以。。。不,没有需要您描述的规范

toString()
方法的输出(除了少数例外)是未指定的,因此理论上不同的Java实现可能会有所不同

然而,大多数商业Java实现都有从Sun/Oracle类库的某些版本派生的类库,无论是OpenJDK代码库还是早期版本。考虑到Sun/Oracle对故意做出可能破坏客户代码的更改持谨慎态度,我认为相应的
toString()
方法基本上是兼容的

但也有一些明显的例外;e、 基于GNU类路径库、ApacheHarvest库和。。。安卓请注意,这些实现没有通过Java遵从性测试(因为Oracle拒绝在可接受的条款下许可TDK!!),所以严格来说,它们不能称为Java(tm)


归根结底,依赖未记录的
toString()
格式可能会导致移植问题或升级JVM版本时出现问题。但在现实中,出现问题的可能性在很大程度上取决于您从何处移植到何处。如果坚持使用Oracle/Sun派生类库的JVM,出现问题的可能性很小


那你该怎么办呢

最极端的情况是避免使用
toString
方法(隐式或显式),除非指定了输出格式。但我认为这太过分了。(这项政策可能很难执行……)

更现实的做法是,在精确的输出格式很重要的情况下,避免使用
toString
方法。换言之:

  • 不要在对象序列化方案中使用
    toString()
    。。。除非指定了格式

  • 如果在单元测试中使用
    toString()
    ,请注意,作为移植工作的一部分,您可能需要修复不可移植的单元测试


+1虽然您不应该期望toString的输出在JVM之间有显著差异,但它应该被视为记录字符串内容的一种方式,并且您不需要在所有实现中都完全相同。它不是序列化内容的手段。“底线是依赖toString()格式可能会导致移植问题。”正如您所说,它可能会导致潜在问题,就像任何移植或JVM升级都可能导致问题一样。只有在文档中这样说时,它们才应该保持一致。在扩展自
AbstractMap
HashMap
的情况下,JVM实现的输出应该是一致的。