gpt4 book ai didi

scala - @elidable 注解在 Scala 中起什么作用,什么时候应该使用它?

转载 作者:行者123 更新时间:2023-12-01 22:19:32 31 4
gpt4 key购买 nike

我注意到在一些 scala 库代码中,特别是 Predef,有这样的代码:

/** Tests an expression, throwing an `AssertionError` if false.
* Calls to this method will not be generated if `-Xelide-below`
* is at least `ASSERTION`.
*
* @see elidable
* @param p the expression to test
*/
@elidable(ASSERTION)
def assert(assertion: Boolean) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed")
}

这个注释允许我在编译时消除代码。当我使用 -Xelide-below MAXIMUM 进行编译时,是否如此

  1. 删除该方法及其所有调用? (如果是这样,如果另一个库期望此方法存在,会发生什么?),我们会得到 NoSuchMethodError 或其他什么吗?
  2. 将方法保留在那里,但删除该方法中的所有代码,留下一个空方法?
  3. 只是删除对该方法的调用,但将方法保留在那里?

我可以用它来减少类的编译大小吗?所以如果我有:

class Foobar {
// extremely expensive toString method for debugging purposes
@elidable(FINE) def toString(): String = "xxx"
}

并使用-Xelide-below 警告进行编译,此类中的toString会完全消失吗?请注意,在此示例中,我希望从类中删除该方法,因为我不希望调用它。

第二部分:我见过it suggested这可用于消除调试日志记录代码。鉴于大多数框架(尤其是 log4j)允许运行时设置日志记录级别,我认为这不是一个好的用例。就我个人而言,我希望保留这段代码。那么除了 Predef 中的assert() 方法之外,@elidable 的一个好的用例是什么?

最佳答案

简短回答

这两个方法以及对它的所有调用都会消失。这对于日志记录来说可能是一个好主意,因为每个日志记录框架在调用日志记录但禁用给定级别(计算有效级别并准备参数)时都会引入一些开销。

请注意,现代日志框架会尝试尽可能减少此占用空间(例如 Logback 优化 is*Enabled() 调用,并且 SLF4S 按名称传递消息以避免不必要的字符串连接) .

长一个

我的测试代码:

import scala.annotation.elidable
import scala.annotation.elidable._

class Foobar {
info()
warning()

@elidable(INFO) def info() {println("INFO")}
@elidable(WARNING) def warning() {println("WARNING")}
}

证明使用 -Xelide-below 800 会打印两个语句,而使用 900 则仅出现 "WARNING"。那么幕后发生了什么?

$ scalac -Xelide-below 800 Foobar.scala && javap -c Foobar

public class Foobar extends java.lang.Object implements scala.ScalaObject{
public void info();
//...

public void warning();
//...

public Foobar();
Code:
0: aload_0
1: invokespecial #26; //Method java/lang/Object."<init>":()V
4: aload_0
5: invokevirtual #30; //Method info:()V
8: aload_0
9: invokevirtual #32; //Method warning:()V
12: return
}

如您所见,编译正常。但是,当使用此指令时:

$ scalac -Xelide-below 900 Foobar.scala && javap -c Foobar

info() 的调用以及方法本身从字节码中消失:

public class Foobar extends java.lang.Object implements scala.ScalaObject{
public void warning();
//...

public Foobar();
Code:
0: aload_0
1: invokespecial #23; //Method java/lang/Object."<init>":()V
4: aload_0
5: invokevirtual #27; //Method warning:()V
8: return

}

我希望当从针对具有较低 elide-belowFoobar 版本编译的客户端代码中调用已删除的方法时,会在运行时抛出 NoSuchMethodError 。临界点 。而且它闻起来像老式的 C 预处理器,因此在使用 @elidable 之前我会三思而后行。

关于scala - @elidable 注解在 Scala 中起什么作用,什么时候应该使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8388952/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com