Java 为什么使用lambdas进行日志记录更好

Java 为什么使用lambdas进行日志记录更好,java,logging,lambda,java-8,Java,Logging,Lambda,Java 8,我经常看到这样的经典结构: if (LOG.isLoggable(Level.FINER)) { LOG.finer("The driver of the car is '"+ car.getDriver().getName() +"'."); } 假设汽车没有驾驶员,则getDriver()返回null LOG.finer的实现可以在这里找到: 然后: getName()无法在null上执行,因此将抛出NPE。只有在一个特殊情况下:我必须让记录器更精细 LOG.isLoggable必须执

我经常看到这样的经典结构:

if (LOG.isLoggable(Level.FINER)) {
  LOG.finer("The driver of the car is '"+ car.getDriver().getName() +"'.");
}
假设汽车没有驾驶员,则
getDriver()
返回
null

LOG.finer
的实现可以在这里找到:

然后:

  • getName()
    无法在
    null
    上执行,因此将抛出NPE。只有在一个特殊情况下:我必须让记录器更精细
  • LOG.isLoggable
    必须执行两次,第一次在
    .finer(
    的方法调用之前执行,第二次在方法内部执行
  • 将在数学运算符
    +
    上创建StringBuilder
  • 我必须导入类
    级别
  • 另一个线程可以将驱动程序设置为
    null
    ,并阻止日志记录此行
  • 如果我改用Lambdas呢

    例如:

    LOG.finer(()->"The driver of the car is '", ()->car.getDriver().getName(), ()->"'.");
    
    finer
    定义为

    public void finer(ObjectReturningFunctionalInterface ... arguments) {
    
    如果捕获所有参数求值异常,我们可以解决在经典样式中看到的所有缺点

    为什么这是个坏主意?


    由于
    lambda
    可以在不同的
    线程中执行
    。因此,这里的变量
    car
    必须是
    final

    我认为是一个更好的主意,一个单独的lambda可以生成整个字符串。从这个意义上说,任何可能需要花费成本才能创建的东西(罕见,imo)仅当使用级别时才会生成。对单个字符串使用varargs lambdas似乎excessive@PeterRader这些可能是事实,但问题的标题可能会吸引人们的意见。你列出的缺点有那么糟糕吗?在我看来,你应该保持传统的方式,而不是仅仅为了清楚起见而有3个lambda。甚至检查日志l在这种情况下,我不会在日志记录之前执行evel。大多数日志记录框架已经允许您添加lambda以提供参数。顺便说一句,编辑:新标题不会有太大变化。“更好”仍然是主观的,除非您明确您想要实现的目标(例如,性能、可读性、避免空指针)3是不正确的。1在任何方面都是一个问题。2是因为你的日志习惯用法来自大约5年前,没有人写过这样的日志。最后两点充其量都是假的。TL;DR:使用一个体面的插值日志。同样已经存在!!你关于多个lambda的建议毫无意义。“由于性能原因,在进行日志记录之前检查日志记录级别”是因为您使用了糟糕的日志记录框架。现代的日志记录框架插入到字符串常量中。没有开销(即字符串concat,
    toString
    调用参数)在这方面。这并不能回答这个问题。若要评论或要求作者澄清,请在他们的帖子下方留下评论。-@barbsan问题是:
    为什么这是个坏主意?
    。坏主意的一个方面是变量car必须是最终的。如果lambda可以异步执行,那么你就有更深的问题了除非传入的每个结构都是完全不可变的,否则要记录的数据可能会在调用日志和完成日志记录之间发生变化。这甚至不会导致在线程之间传递不应该在线程之间传递的内容的可见性问题。最后,没有双关语lambda中使用的变量实际上是final与线程无关。即使此注释可以归类为答案,也绝对不正确。@Boristeider我永远不会登录其他线程!这个想法太疯狂了。@Boristeider任何NPE stacktrace都是无用的!