【问题标题】:Am I abusing toString()?我在滥用 toString() 吗?
【发布时间】:2018-04-26 19:49:26
【问题描述】:

Object.toString() 的 Javadoc 说:

返回对象的字符串表示形式。一般来说, toString 方法返回一个“以文本形式表示”的字符串 目的。结果应该是简洁但信息丰富的表示 这对一个人来说很容易阅读。建议所有 子类覆盖此方法。类 Object 的 toString 方法 返回一个字符串,该字符串由该类的名称组成 object 是一个实例,at-sign 字符 '@' 和 unsigned 对象的哈希码的十六进制表示。其他 换句话说,这个方法返回一个等于值的字符串:

getClass().getName() + '@' + Integer.toHexString(hashCode())

因此,当我覆盖 Foo 类的 toString() 时,我质疑自己是否在滥用它,以便 ComboBox 控件(不管是 JavaFX 还是 Swing 控件)可以呈现一个列表Foo 正确,无需我在 ComboBox 中做任何明确的操作。

class Foo {
    private String name;
    public final String getName() { return name; }
    public final void setName(String n) { name = n; }

    @Override
    public String toString() {
        return name;
    }
}

List<Foo> foos = getFoos(); // Get list of Foos from somewhere
ComboBox comboBox = ....; // Some ComboBox control
comboBox.addItems(foos); // Add the list to the ComboBox

大多数 IDE 生成的 toString() 的默认实现是类的 JSON 表示。我怀疑这允许类对象的轻松序列化/反序列化。虽然我不需要通过这种方法进行序列化或反序列化,但是我这样重写肯定是打破了这种可能性。

编辑

看了很多人的cmet,还有VGR给出的答案。我可以看到,普遍的共识是,对此没有硬性规定。我看到大家普遍认为toString() 最好留作调试用途。

我做这个“hack”的最大原因是因为我在很多不同的地方都有ComboBox。当然,无可争议的正确和干净的方法是使用“渲染器”来完成这项工作,但这会导致大量代码重复。

我会考虑几天,然后再决定哪种方法是最好的。非常感谢各位cmets的解答。

【问题讨论】:

  • 见仁见智,根据我的经验,是有分歧的。使用toString 表示演示信息可能是一个好主意(JList 或示例根据toString 的结果提供元素的键盘突出显示)有一些原因 - 对我来说,这只是糟糕的设计。在 Swing 和 JavaFX 中,您有装饰器/渲染器,您应该使用它们来确定给定对象在给定上下文中应如何显示。这意味着在 JList 中它可能看起来与在 JComboBox 中显示时不同,等等 - 但这只是我的意见
  • 简短回答不,这就是它可以被覆盖的原因。对于更复杂的多字段对象,您甚至可以使用它来生成某种连接字符串以进行调试。
  • 恕我直言 - 离开 toString 进行调试,使用 GUI API 根据您尝试显示它的上下文提供演示。是的,它可能需要一些额外的编码来进行设置,但是一次你已经启动并运行了,这很容易(而且灵活)
  • 你需要考虑的是覆盖默认值是否会给Foo的消费者带来问题。如果有任何疑问,那就不要。
  • 看看代码你有一个 Public getName() 方法为什么不使用它。

标签: java combobox tostring


【解决方案1】:

对于 Swing,你肯定需要重写 some 类的 toString 方法。这就是 Swing 模型对象的工作方式。 (不要使用单元格渲染器将值转换为字符串;这会破坏可访问性、键盘导航和 JTable 的内置排序。)

通常您希望将显示逻辑与数据分开,例如通过创建包装类,但由于您只是返回属性的原始值(而不是对其进行格式化或将其与其他信息连接) ,你做的很好。

JavaFX 是另一回事:控件使用单元格工厂回调对象来确定单元格中显示的文本,因此数据类可能不应该用 JavaFX 应用程序中的显示值覆盖 toString

我不熟悉 IDE 自动生成的 toString 方法,但在我看来,在 toString 方法中将对象转换为 JSON 是一个可怕的想法。 Swing 模型对象应该有一个 toString 方法,该方法返回对象的人类可读形式;大多数其他类应该返回一个包含对象状态摘要的单行字符串(不必是对象中的每个属性),例如getClass().getName() + "[" + getName() + "]"

总之,你没有滥用 toString。对于 Swing,您正在做正确的事情。对于 JavaFX,最好返回一个对调试有用的字符串。

【讨论】:

  • 其实我的实际环境是JavaFX。我做了这个“hack”,因为我多次重复相同的单元工厂回调代码,因为我有很多视图需要将Foos 的列表呈现为ComboBox
  • 通常,您需要创建一个 TableCell 子类,以使重复设置单元工厂变得轻松,因为它们可以指定为单行 lambda:control.setCellFactory(c -&gt; new FooCell());
猜你喜欢
  • 2011-05-07
  • 2018-06-14
  • 2015-07-30
  • 2014-10-30
  • 2011-05-31
  • 2016-07-03
  • 2015-03-29
  • 2014-03-31
  • 2016-09-16
相关资源
最近更新 更多