什么时候不希望在Java中实现toString()?

时间:2009-07-21 19:27:11

标签: java tostring

我项目的首席开发人员已经将项目的toString()实现称为“pure cruft”,并希望将它们从代码库中删除。

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

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

那么,人群在哪里撒谎?

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

24 个答案:

答案 0 :(得分:68)

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

就个人而言,我总是会因为有一个可行的toString()方法而犯错误。写作的工作很少。

答案 1 :(得分:35)

去除写得很好(甚至中途写得好)toString()方法是纯疯狂的,IMO。是的,我经常懒得写这些(因为这些对象通常不会最终使用它们),但它们非常方便。

我真的想不出想要摆脱这些的好理由。

答案 2 :(得分:18)

我总是确保我的类实现了toString。

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

答案 3 :(得分:15)

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

答案 4 :(得分:12)

我认为相反,toString()应该明智地重写。默认的toString()实现是非常无法提供的,基本上没用。一个好的toString()实现可以为开发人员提供一个非常有用的对象内容视图。你可能不必把所有东西放在那里,但至少是重要的东西。我认为你的首席开发人员应该实际编码和添加功能,而不是担心“残酷”。

答案 5 :(得分:11)

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

对于其他一切,比如JavaBeans,如果需要进行低级调试,我希望客户端代码将我的对象抛出到ToStringBuilder method或类似的对象中。

ToStringBuilder.reflectionToString(myObject);

或客户端代码应该只调用标准属性getter并以他们喜欢的方式记录...

答案 6 :(得分:7)

一般来说,toString()是好事。特别是,非常适合调试

实施toString()并非没有成本风险。与所有代码一样, toString()实现必须与其余代码一起维护。这意味着保持toString()与类字段同步。例如,添加或删除字段时,toString()应该适当更新(您应该对hashCode()equals()等方法执行此操作。

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

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

答案 7 :(得分:6)

我总是自动生成 toString()方法,用于我的所有POJODTO和/或任何持有持久数据的对象。对于私人内部物业,良好的伐木实践应该可以解决问题

始终记得用[Omitted] (或类似顶级性质的东西)替换toString方法密码和其他敏感信息

答案 8 :(得分:4)

嗯,他确实扼杀了事情。

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

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

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

答案 9 :(得分:4)

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

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

答案 10 :(得分:3)

+1 Mike C

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

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

答案 11 :(得分:2)

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

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

答案 12 :(得分:2)

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

否则,我同意开发人员 - 每次更改内容时,toString都会中断。您可能必须小心空值等。

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

我同意jsight,如果他们已经写好并写得不错,请至少留下它们,直到它们妨碍(例如你实际上在课堂上添加一个字段)。

答案 13 :(得分:2)

这很有道理,因为你总是遇到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

答案 14 :(得分:2)

  

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

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

答案 15 :(得分:2)

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

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

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

答案 16 :(得分:2)

我肯定会保留toString()实现,特别是出于调试目的。作为一个主要的C ++开发人员,我希望在这方面C ++中的东西和在Java中一样简单(运算符重载可能很麻烦)。

答案 17 :(得分:2)

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

强烈阻止开发者删除任何正常运行的toString()方法。

答案 18 :(得分:2)

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

也许你可以反击许多JDK类都有toString()。他们也应该被删除吗? ;)

答案 19 :(得分:1)

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

答案 20 :(得分:1)

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

关于

  

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

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

答案 21 :(得分:0)

尽管{{1}}方法对于调试值类非常有用,但可以认为它们是not useful for entity classes

答案 22 :(得分:0)

鉴于这个问题现在已经有10年历史了,我认为自己会以更现代的视角来考虑。

# in app/model/order.rb before_validation :connect_user private def connect_user self.buyer ||= User.find_by(email: self.email) end 显然对调试很有帮助-您只需要看这里所有其他答案即可证明这一点-但调试信息不​​是业务逻辑

每个单独的类中都有一个toString方法,这是视觉上的混乱,它掩盖了该类的有用行为。我们还需要记住,每次更改类字段时,都要手动或通过从IDE重新生成方法来对其进行维护。

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

基本样本用法:

toString

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

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

答案 23 :(得分:-1)

我们从一个toString()方法中抛出了一个ConcurrentModificationException,因此偶尔会有一个缺点。当然,没有让它同步是我们自己的错。