代码之家  ›  专栏  ›  技术社区  ›  James A. N. Stauffer

一般认为toString()的成本较低是否安全?

  •  13
  • James A. N. Stauffer  · 技术社区  · 16 年前

    您是否通常认为任何给定对象上的toString()成本较低(即用于日志记录)?我愿意。这个假设有效吗?如果它的成本很高,通常应该改变它吗?什么是使ToString()方法具有高成本的有效原因?我唯一一次关心的是控制成本,当我知道它是在某种类型的集合与许多成员。 来自: http://jamesjava.blogspot.com/2007/08/tostring-cost.html

    更新:另一种说法是:在调用任何给定类之前,您通常会考虑调用ToString的成本吗?

    17 回复  |  直到 16 年前
        1
  •  19
  •   Eli Courtwright    16 年前

    Java标准库似乎是为了保持ToStk调用的成本非常低而编写的。例如,Java数组和集合有ToString方法,它们不迭代它们的内容;为了获得这些对象的良好字符串表示,您必须使用 Arrays.toString Collections.toString java.util 包裹。

    类似地,即使使用昂贵的equals方法的对象也有不昂贵的字符串调用。例如, java.net.URL 类有一个equals方法,该方法使用Internet连接来确定两个URL是否真正相等,但它仍然有一个简单且持续的时间字符串方法。

    所以是的,便宜的电话串是正常的,除非你使用一些奇怪的第三方包打破了惯例,你不应该担心这些需要很长时间。

    当然,在你发现你的程序花费了太长时间之前,你不应该真的担心性能,即使这样,你也应该使用一个分析器来找出花费了这么长时间的原因,而不是提前担心这类事情。

        2
  •  37
  •   Blair Conrad    16 年前

    不,不是。因为ToString()可以被任何人重载,所以他们可以随心所欲。ToString()的成本应该很低,这是一个合理的假设,但是如果ToString()访问执行“延迟加载”数据的属性,那么您甚至可能会访问ToString()内的数据库。

        3
  •  9
  •   Ovid    16 年前

    最好的方法是分析代码。但是,与其担心某个特定函数的开销很高,不如(通常)先担心应用程序的正确性,然后再对其进行性能分析(但请注意,实际使用和测试设置可能存在根本差异)。结果表明,程序员通常对应用程序中的真正慢的地方猜错了,他们经常花费大量时间优化不需要优化的东西(消除只占用应用程序0.01%时间的三重嵌套循环可能是浪费)。

    幸运的是,有很多 open source profilers for Java .

        4
  •  5
  •   Shog9    16 年前

    您一般认为任何给定对象上的toString()都具有较低的成本吗?我愿意。

    你为什么要这样做? 简况 如果您遇到性能问题,您的代码将节省大量时间来处理错误的假设。

        5
  •  3
  •   Larry OBrien    16 年前

    你的问题标题使用了自相矛盾的词“安全”和“一般”。因此,即使在评论中,你似乎强调了一般情况,答案可能是“是的,这通常不是问题”,很多人看到“安全”,因此回答要么是“否,因为存在随意表现不佳的风险”,或“不,因为如果你想在性能问题上“安全”,你 必须 外形。”

        6
  •  1
  •   Chris J    16 年前

    因为我通常只对自己编写的方法和类调用ToString(),并覆盖了基方法,所以我通常提前知道成本是多少。否则,我唯一一次使用toString()是在速度不重要时进行错误处理和或调试。

        7
  •  1
  •   Confusion    16 年前

    我的实际答案是:是的,你总是假设一个toString()调用是便宜的,除非你做了大量的调用。一方面,toString()方法极不可能昂贵,另一方面,如果它不昂贵,则极不可能遇到麻烦。我通常不担心这些问题,因为它们太多,如果这样做,就不会编写任何代码;)。

    如果确实遇到性能问题,那么一切都是开放的,包括toString()的性能,您应该像shog9建议的那样,简单地分析代码。这个 Java Puzzlers 说明甚至Sun也在其JDK中编写了一些非常讨厌的构造函数和toString()方法。

        8
  •  1
  •   Nathan Feger    16 年前

    我认为这个问题有缺陷。我甚至不认为ToString()会打印一个有用的数据。所以,如果你从这个假设开始,你知道你必须在打电话之前检查它,并且可以根据具体情况评估它的“成本”。

        9
  •  0
  •   EfForEffort    16 年前

    NaiveToString()链接的最大成本可能是追加所有这些字符串。如果要生成大字符串,则应使用支持有效附加的基础表示形式。如果您知道附加是有效的,那么toString()s的成本可能相对较低。

    例如,在Java中,StringBuilder将预先分配一些空间,使得一定数量的字符串追加需要线性时间。当空间耗尽时,它会重新分配。

    一般来说,如果你想附加一系列的事情,而你出于任何原因不想做类似的事情,你可以使用 difference lists . 它们通过将序列附加转换为函数组合来支持线性时间附加。

        10
  •  0
  •   Mike Pone    16 年前

    toString()用于将对象表示为字符串。因此,如果需要运行缓慢的代码来创建对象的表示形式,则需要 非常小心 有很好的理由这么做。调试是我能想到的唯一一个可以接受缓慢运行的toString的地方。

        11
  •  0
  •   workmad3    16 年前

    我的想法是:

    对标准库对象是

    非标准对象上没有,除非您前面有源代码并且可以检查它。

        12
  •  0
  •   Javamann    16 年前

    我将始终重写toString以放入我认为需要的任何内容来调试问题。通常由开发人员决定使用它,要么调用ToString方法本身,要么让另一个类为您调用它(println、logging等)。

        13
  •  0
  •   apenwarr    16 年前

    对于这个问题,有一个简单的答案,我在一次关于思考的讨论中第一次听到:“如果你必须问,你负担不起。”

    基本上,如果您需要在程序的日常操作中对大型对象进行字符串(),那么您的程序就是疯狂的。即使您需要为任何时间关键的事情字符串(),您的程序也是疯狂的,因为显然它使用的是一个字符串,整数可以做到这一点。

    日志消息的toString()自动正常,因为日志记录已经很昂贵了。如果程序太慢,请降低日志级别!实际上生成调试消息的速度有多慢并不重要,只要您可以选择不生成它们。(注意:您的日志基础结构应该调用toString()本身,并且只在应该打印日志消息时调用。不要在路上用手把它串起来。 进入之内 日志基础设施,否则即使日志级别很低,您也要付出代价,毕竟您不会打印它!参见 http://www.colijn.ca/~caffeine/?m=200708#16 更多解释。)

        14
  •  0
  •   Mike Comstock    16 年前

    既然你的问题是“一般性”的,我会说是的。对于大多数对象来说,不会有代价高昂的字符串过载。当然可以,但一般不会。

        15
  •  0
  •   Scott Ainsworth    16 年前

    一般来说,当我在简单对象上使用toString()时,我认为它成本很低,比如整数或非常简单的结构。然而,当应用于复杂对象时,toString()有点垃圾。这有两个原因。首先,复杂对象往往包含其他对象,因此对ToString()的单个调用可以级联到对其他对象的多个ToString()调用中,再加上连接所有这些结果的过度开销。第二,没有将复杂对象转换为字符串的“标准”。一个toString()调用可能产生一行逗号分隔的值;另一个则是一个更详细的形式。只有亲自检查才能知道。

    所以我的规则是在简单对象上使用toString()通常是安全的,但是在复杂对象上使用toString()直到被检查。

        16
  •  0
  •   Mr. Shiny and New 安宇    16 年前

    我将避免在基本类型以外的对象上使用toString()。ToString()可能无法显示任何有用的内容。它可以迭代所有成员变量并将其打印出来。它可能加载尚未加载的内容。根据您计划如何处理该字符串,您应该考虑不构建它。

    使用toString()的原因通常有几个:对于随机对象,日志记录/调试可能是最常见的;对于某些对象(如数字),显示是常见的。为了记录我会做一些像

    if(logger.isDebugEnabled()) {
        logger.debug("The zig didn't take off.  Response: {0}", response.getAsXML().toString());
    }
    

    这有两件事:1.阻止构造字符串和2。防止在不记录消息的情况下添加不必要的字符串。

        17
  •  0
  •   erickson    16 年前

    一般来说,我不会检查每个实现。但是,如果我看到对ApacheCommons的依赖,就会发出警报,我会更仔细地查看实现,以确保它们不会使用 ToStringBuilder 或其他暴行。