【问题标题】:When is it desired to not implement toString() in Java?什么时候不希望在 Java 中实现 toString()?
【发布时间】:2009-07-21 19:27:10
【问题描述】:

我项目的一位主要开发人员已将项目的 toString() 实现称为“纯粹的垃圾”,并希望将它们从代码库中删除。

我说过这样做意味着任何希望显示对象的客户都必须编写自己的代码来将对象转换为字符串,但回答是“是的,他们会”。

现在具体来说,这个系统中的对象是矩形、圆形等图形元素,当前的表示是显示 x、y、比例、边界等......

那么,人群在哪里?

什么时候应该和什么时候不应该实现 toString?

【问题讨论】:

  • 哇,我期待更多的争论。
  • 似乎对保留它们达成了共识。我想知道您的首席开发人员想要删除它们的动机是什么?表现?维护?重构麻烦?如果我们能更好地理解他的动机,那可能会导致更好的争论。
  • 我认为最佳实践是原因,它作为最佳实践表现不佳。
  • 你的领导是疯了。如果这反映了您的领导的典型想法,您可能会考虑寻找另一份工作......
  • 嗯...这家伙是如何成为“领导”的?他需要被解雇......或者你需要找到一份新工作。

标签: java tostring


【解决方案1】:

它们有什么害处?如果有它们,为什么要删除它们?我发现 toString() 在发出调试语句时非常有用。

就个人而言,我总是倾向于使用可行的 toString() 方法。写的工作太少了。

【讨论】:

  • toString() 用于调试非常有用,以至于 Eclipse 允许您为无法编辑的库中的类提供自己的“toString()”覆盖。该功能称为“详细格式化程序”。
  • HaroldL:您能否详细说明如何使用该功能?我是 Eclipse 用户,这是我第一次听说它,所以我一定会寻找它。
  • 一段调试对于其他人在未来捡起它就像金子一样......把它们留在他们不会造成任何伤害。
  • Thomas:在“变量”窗格中查找“New detail formatter”弹出菜单项。
  • 详细格式化程序:javalobby.org/java/forums/t16350.html。 Window->Preferences->Java->Debug->Detail Formatters
【解决方案2】:

删除写得很好(甚至写得半点体面)的 toString() 方法是纯粹的疯狂,IMO。是的,我经常懒得写这些(因为通常这些对象最终并没有被使用),但它们非常方便。

我真的想不出一个很好的理由来摆脱这些。

【讨论】:

  • 是的,完全正确。删除现有的 toString() 方法没有充分的理由。此外,即使是不完整的,在调试时也很有用。
【解决方案3】:

我一直确保我的类实现了 toString。

它提供了一种简单的方法来在我调试时调试类的当前状态,当我记录错误时,我可以将它包含到我的日志消息中。

【讨论】:

    【解决方案4】:

    我会保留 toString() 实现。它们在调试方面非常宝贵,它们可以为图形组件提供良好的替代文本。

    【讨论】:

      【解决方案5】:

      我反对 toString() 应该被明智地覆盖。默认的 toString() 实现是非常无用的,基本上没用。一个好的 toString() 实现可以让开发人员一目了然地了解对象的内容。你可能不必把所有东西都放在那里,但至少重要的东西。我认为您的首席开发人员实际上应该编码和添加功能,而不是担心“粗鲁”。

      【讨论】:

      • 如果您不需要自省字段,默认的 toString 非常简洁且有用。
      【解决方案6】:

      我只会为更复杂的对象实现它,其中客户端代码不关心对象状态的细粒度细节,而是关心一些更易于人类理解的、有意义的消息,总结正在发生的事情,状态明智的...

      对于其他所有内容,例如 JavaBeans,如果需要进行低级调试,我希望客户端代码将我的对象放入 ToStringBuilder method 或类似文件中。

      ToStringBuilder.reflectionToString(myObject);
      

      或者客户端代码应该只调用标准属性获取器并按照他们喜欢的方式记录......

      【讨论】:

      • 这是一个巧妙的技巧,但我不得不猜测大多数人从未听说过。此外,还需要考虑哪些工作:下载 Apache Lang 库并将其添加到您的程序中,还是直接使用已经存在并可以使用的 toString 方法?
      【解决方案7】:

      一般来说,toString() 是好东西。特别是,它对调试非常有用

      实施toString() 并非没有成本风险。与所有代码一样,toString() 实现必须与其余代码一起维护。这意味着保持toString() 与类字段同步。例如,当添加或删除一个字段时,toString() 应该被适当地更新(你应该已经为hashCode()equals() 等方法这样做了)。

      实施toString() 也会带来风险。例如,假设您系统中的两个类引用了另一个类的实例(双向链接),那么 toString() 的调用可能会由于无限递归而导致堆栈溢出每个类中的toString() 实现调用另一个类的toString() 实现。

      如果您的系统有大量不同步的toString() 方法,或者导致堆栈溢出等错误的方法,那么您的同事可能有一个合理的观点。即使在这种情况下,我也会简单地将错误的toString() 方法注释掉,然后将它们留在代码中。每个toString() 方法都可以取消注释并在未来根据需要单独更新。

      【讨论】:

        【解决方案8】:

        我总是为我的所有POJOs、DTOs 和/或任何保存持久数据的对象自动生成 toString() 方法。对于私有内部属性,良好的日志记录实践应该可以解决问题。

        永远记得用[Omitted](或类似绝密性质的东西)替换 toString 方法中的密码和其他敏感信息

        【讨论】:

          【解决方案9】:

          嗯,他做的事情很奇怪。

          我不能说 toString() 太有用了。为了演示,您将需要其他工具。

          但是 toString() 对调试非常有用,因为你可以看到集合的内容。

          我不明白为什么已经写好了为什么要删除它

          【讨论】:

            【解决方案10】:

            我认为答案取决于您的 toString() 方法的复杂程度、需要维护的工作量以及使用频率。假设您经常使用 toString() 进行日志记录和调试,那么删除这些方法没有多大意义。但是,如果它们很少使用,并且每次代码发生更改时都需要大量工作来维护,那么可能有一个有效的论据可以摆脱所有或部分 toString() 方法。

            您提到了需要显示这些对象的客户端。由此我猜测您的代码是或包含其他开发人员将使用的某种库或 API。在这种情况下,我强烈建议您维护有用的 toString() 实现。即使您没有进行大量的日志记录和调试,您的客户也可能而且他们肯定会喜欢有有用的 toString() 方法,而他们不必自己编写和维护。

            【讨论】:

              【解决方案11】:

              +1 迈克 C

              除了对调试有用之外,toString() 是理解类作者对实例的看法的宝贵工具。

              FWIW,如果 toString 的输出与您期望看到的不同(礼貌的规范文档),您会立即知道发生了严重错误。

              【讨论】:

                【解决方案12】:

                就我个人而言,当我要在 JList、JTable 或其他使用 toString() 的结构中使用对象时,或者在调试时(是的,eclipse 有调试格式化程序,但 toString() 更容易),我会实现它们.

                也许您可以回击许多 JDK 类都有 toString()。它们也应该被删除吗? ;)

                【讨论】:

                  【解决方案13】:

                  如果这是预期的用例或要求,我会说您应该实现 toString,以将对象显示为字符串表示形式(在日志中、控制台上或某种显示树中)。

                  否则,我同意开发人员的观点 - 每次更改某些内容时,toString 都会中断。您可能需要注意空值等。

                  但很多时候,它实际上用于调试或日志记录,因此根本不应该忽略它们。

                  我同意 jsight 的观点,如果它们已经写好了,并且写得体面,至少在它们妨碍它们之前将它们留在里面(比如你实际上向一个类添加了一个字段)。

                  【讨论】:

                    【解决方案14】:

                    出于调试目的,没有人能击败toString。它在调试器和简单的调试打印中都很实用。确保它显示您的 equalshashCode 方法所基于的所有字段,如果您也覆盖这些字段!

                    不过,为了向最终用户显示,我不会使用toString。为此,我认为最好编写另一种方法,该方法可以进行正确的格式化,如果需要,还可以使用 i18n。

                    【讨论】:

                      【解决方案15】:

                      这很有意义,因为您总是遇到 toStrings 显示太少或太多信息的问题。

                      在 Jakarta Commons Lang 中使用 ToStringBuilder 可能对您的团队有意义:

                      System.out.println("An object: " + ToStringBuilder.reflectionToString(anObject));
                      

                      内省对象,并打印出公共字段。

                      http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/builder/ToStringBuilder.html

                      【讨论】:

                        【解决方案16】:

                        我说过这样做意味着 任何希望展示的客户 对象必须写他们的 自己的代码将对象转换为 字符串,但答案是 “是的,他们会”。

                        这不是一个可以孤立地回答的问题......您应该询问客户(或编写它们的人)他们对这个想法的看法。如果我使用 Java 库并依赖其 toString() 重载进行调试,那么如果库的开发人员决定清除它们,我会非常恼火。

                        【讨论】:

                          【解决方案17】:

                          公平地说,这里说的是开发人员,但不是任何意义上的领导开发人员。

                          原来的问题不一定是关于toString(),而是关于第二种方法paramString: “通过所有字符串连接和空值检查,paramString 是一个错误磁铁。”

                          http://code.google.com/p/piccolo2d/issues/detail?id=99

                          【讨论】:

                            【解决方案18】:

                            我肯定会保留 toString() 实现,尤其是出于调试目的。作为一个主要从事 C++ 的开发人员,我希望在这方面 C++ 和 Java 一样简单(操作符重载可能会很痛苦)。

                            【讨论】:

                              【解决方案19】:

                              如果现有的toString() 实现存在问题,开发人员应该解决问题。除非现有的 toString() 方法不常见写得不好,否则说当前的实现都是“纯粹的垃圾”并且删除它们正在积极造成伤害。

                              我会强烈劝阻开发人员删除任何功能正常的toString() 方法。

                              【讨论】:

                                【解决方案20】:

                                始终实现 :) 如上所述,它对于调试非常宝贵。

                                【讨论】:

                                  【解决方案21】:

                                  它有利于调试目的。但是如果你想将给定的对象作为字符串显示给最终用户,你不应该使用 toString() 实现,而是为此提供自定义方法。

                                  所以关于

                                  我说过这样做意味着 任何希望展示的客户 对象必须写他们的 自己的代码将对象转换为 字符串,但答案是 “是的,他们会”。

                                  我同意您的团队负责人的观点。如果要向任何客户端显示对象,请使用自定义实现。如果您想将其用于调试目的,请使用 toString()。

                                  【讨论】:

                                    【解决方案22】:

                                    虽然toString() 方法对于调试值类非常有用,但可以说它们是not useful for entity classes

                                    【讨论】:

                                      【解决方案23】:

                                      考虑到这个问题已经有将近 10 年的历史了,我想我会以更现代的视角来衡量。

                                      toString 显然有助于调试 - 您只需查看此处证明这一点的所有其他答案 - 但调试信息不​​是业务逻辑

                                      在每个类中都有一个toString 方法是视觉上的混乱,它会掩盖类的有用行为。我们还需要记住在每次更改类字段时维护它 - 无论是手动还是通过从我们的 IDE 重新生成方法。

                                      那么在不完全删除该方法的情况下,我们可以做些什么来解决这些问题呢?答案是自动生成Project Lombok's @ToString annotation 可以在编译时自动为您生成 toString 方法,其中包括您选择的任何字段组合。

                                      基本示例用法:

                                      @ToString
                                      public class Foo {
                                          private int i = 0;
                                      }
                                      

                                      这将在编译时等同于以下内容:

                                      public class Foo {
                                          private int i = 0;
                                      
                                          public String toString() {
                                              return "Foo(i=" + this.i + ")";
                                          }
                                      }
                                      

                                      【讨论】:

                                        【解决方案24】:

                                        我们的 toString() 方法之一抛出了 ConcurrentModificationException,因此偶尔会出现问题。没有同步当然是我们自己的错。

                                        【讨论】:

                                          猜你喜欢
                                          • 2011-03-22
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 2013-09-09
                                          • 1970-01-01
                                          • 2019-02-16
                                          • 2014-01-25
                                          相关资源
                                          最近更新 更多