我项目的一位主要开发人员已将项目的 toString() 实现称为“纯粹的垃圾”,并希望将它们从代码库中删除。
我说过这样做意味着任何希望显示对象的客户都必须编写自己的代码来将对象转换为字符串,但回答是“是的,他们会”。
现在具体来说,该系统中的对象是矩形、圆形等图形元素,当前表示是显示 x、y、比例、边界等......
那么,人群在哪里?
什么时候应该,什么时候不应该实现 toString?
他们有什么害处?如果有它们,为什么要删除它们?我发现 toString() 在发出调试语句时非常有用。
就个人而言,我总是宁愿拥有一个可行的 toString() 方法。写的工作太少了。
删除写得很好(甚至写得体面)的 toString() 方法是纯粹的疯狂,IMO。是的,我经常懒得写这些(因为通常这些对象最终并没有被使用),但它们非常方便。
我真的想不出一个很好的理由来摆脱这些。
我一直确保我的类实现了 toString。
它提供了一种简单的方法来调试类的当前状态,当我在调试和记录错误时,我可以将它包含到我的日志消息中。
我会保留toString()
实现。它们在调试方面非常宝贵,它们可以为图形组件提供良好的替代文本。
我认为应该明智地覆盖 toString() 的观点正好相反。默认的 toString() 实现是非常无用的,基本上没用。一个好的 toString() 实现可以让开发人员对对象的内容一目了然。你可能不必把所有东西都放在那里,但至少重要的东西。我认为您的首席开发人员实际上应该编写代码和添加功能,而不是担心“杂乱无章”。
我只会为更复杂的对象实现它,其中客户端代码不关心对象状态的细粒度细节,而是关心一些更易于人类理解的、有意义的消息,它总结了正在发生的事情,状态明智.. .
对于其他所有内容,例如 JavaBeans,如果需要进行低级调试,我希望客户端代码将我的对象放入ToStringBuilder 方法或类似方法中。
ToStringBuilder.reflectionToString(myObject);
或者客户端代码应该只调用标准属性获取器并以他们喜欢的方式记录......
总的来说,toString()
是好东西。特别是,它对于调试非常有用。
实施toString()
并非没有成本和风险。与所有代码一样,toString()
实现必须与其余代码一起维护。这意味着toString()
与类字段保持同步。例如,当一个字段被添加或删除时,应该适当地更新(你应该已经为和toString()
之类的方法这样做了)。hashCode()
equals()
实施也会toString()
带来风险。例如,假设您系统中的两个类引用了另一个类的实例(双向链接),那么由于无限递归,调用toString()
可能导致堆栈溢出,因为toString()
每个类中的实现都toString()
调用其他类。
如果您的系统有大量不同步的toString()
方法,或者导致堆栈溢出等错误的方法,那么您的同事可能有一个合理的观点。即使在这种情况下,我也会简单地注释掉错误的toString()
方法并将它们留在代码中。每种toString()
方法都可以取消注释并在将来根据需要单独更新。
我总是为我的所有s、s 和/或任何保存持久数据的对象自动生成toString() 方法。对于私有内部属性,良好的日志记录实践应该可以解决问题。POJO
DTO
永远记得在 toString 方法中将密码和其他敏感信息替换为[Omitted]
(或类似绝密性质的东西)
嗯,他做奇怪的事情。
我不能说 toString() 太有用了。对于演示,您将需要其他工具。
但是 toString() 对于调试非常有用,因为你可以看到集合的内容。
我不明白如果已经写了为什么要删除它
我认为答案取决于您的 toString() 方法的复杂程度、需要维护的工作量以及使用频率。假设您经常使用 toString() 进行日志记录和调试,那么删除这些方法没有多大意义。但是,如果它们很少使用并且每次代码中发生更改时都需要大量工作来维护,那么可能有一个有效的论据可以摆脱所有或部分 toString() 方法。
您提到了需要显示这些对象的客户端。据此,我猜测您的代码是或包含其他开发人员将使用的某种库或 API。在这种情况下,我强烈建议您维护有用的 toString() 实现。即使您没有进行大量的日志记录和调试,您的客户也可能而且他们肯定会喜欢有有用的 toString() 方法,而他们不必自己编写和维护。
+1 迈克 C
除了对调试有用之外,toString() 是理解类作者对实例的看法的宝贵工具。
FWIW,如果 toString 的输出与您期望看到的不同(礼貌的规范文档),您将立即知道发生了严重错误。
就个人而言,当我要在 JList、JTable 或其他使用 toString() 的结构中使用对象时,或者在调试时(是的,eclipse 有调试格式化程序,但 toString() 更容易),我会实现它们。
也许您可以回击许多 JDK 类都有 toString()。它们也应该被删除吗?;)
如果这是预期的用例或要求,我会说您应该实现 toString ,以将对象显示为字符串表示形式(在日志中、控制台上或某种显示树中)。
否则,我同意开发人员的意见 - 每次您更改某些内容时,toString 都会中断。您可能必须小心空值等。
但很多时候,它实际上用于调试或日志记录,因此完全不应该将它们排除在外并不明显。
我同意 jsight 的观点,如果它们已经编写好了,并且写得体面,至少在它们妨碍它们之前将它们留在里面(例如,您实际上将一个字段添加到一个类中)。
出于调试目的,没有人可以击败toString
. 它在调试器和简单的调试打印中都很实用。确保它显示您equals
和hashCode
方法所基于的所有字段,如果您也覆盖这些字段!
不过,为了向最终用户显示,我不会使用toString
. 为此,我认为最好编写另一种方法,该方法进行正确的格式化,如果需要,还可以使用 i18n。
这很有意义,因为您总是会遇到 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
我说过这样做意味着任何希望显示对象的客户都必须编写自己的代码来将对象转换为字符串,但回答是“是的,他们会”。
这不是一个可以孤立地回答的问题……您应该询问客户(或编写它们的人)他们对这个想法的看法。如果我使用 Java 库并依赖它的 toString() 重载进行调试,那么如果库的开发人员决定清除它们,我会非常恼火。
公平地说,这里的开发人员说,但不是任何意义上的领导开发人员。
最初的问题不一定是关于 toString(),而是关于第二种方法 paramString:“通过它的所有字符串连接和空值检查,paramString 是一个错误磁铁。”
我肯定会保留 toString() 实现,特别是出于调试目的。作为主要的 C++ 开发人员,我希望 C++ 中的事情在这方面和 Java 中一样简单(运算符重载可能会很痛苦)。
如果现有toString()
实现存在问题,则开发人员应解决该问题。说当前的实现都是“纯粹的垃圾”并且删除它们正在积极地造成伤害,除非现有的toString()
方法写得非常糟糕。
我强烈劝阻开发人员不要删除任何有效的toString()
方法。
始终执行 :) 如上所述,它对于调试非常宝贵。
它有利于调试目的。但是,如果您想将给定对象作为字符串显示给最终用户,则永远不应使用 toString() 实现,而是为此提供自定义方法。
所以关于
我说过这样做意味着任何希望显示对象的客户都必须编写自己的代码来将对象转换为字符串,但回答是“是的,他们会”。
我同意你的团队领导。如果要向任何客户端显示对象,请使用自定义实现。如果您想将其用于调试目的,请使用 toString()。
尽管toString()
方法对于调试值类非常有用,但可以说它们对实体类没有用。
鉴于这个问题现在已经有将近 10 年的历史了,我想我会以更现代的观点来衡量。
toString
显然对调试很有帮助-您只需查看此处证明这一点的所有其他答案即可-但调试信息不是业务逻辑。
toString
在每个类中都有一个方法是视觉上的混乱,它掩盖了类的有用行为。我们还需要记住在每次更改类字段时维护它——无论是手动还是通过从我们的 IDE 重新生成方法。
那么在不完全删除该方法的情况下,我们可以做些什么来解决这些问题呢?答案是自动生成它。Project Lombok 的@ToString
注释可以在编译时自动为您生成一个toString
方法,其中包括您选择的任何字段组合。
基本示例用法:
@ToString
public class Foo {
private int i = 0;
}
这将在编译时等效于以下内容:
public class Foo {
private int i = 0;
public String toString() {
return "Foo(i=" + this.i + ")";
}
}
我们的 toString() 方法之一抛出了 ConcurrentModificationException,因此偶尔会有一个缺点。当然,不同步是我们自己的错。