4

我知道所有反对 Java 中的预处理器和宏的哲学论点。我不同意仅仅因为某些人可能滥用语言功能,就应该将其排除在外。

我想在我的 Java 和 Scala 代码中包含__FILE__和宏,以实现高效的日志记录。__LINE__由于运行时性能影响,任何使用 Exception 都是不可接受的。那些认为可以在“生产代码”中关闭日志记录的人应该听从 Brian Kernighan 的建议:

删除“现在程序正在运行”的错误消息就像在地面上戴降落伞,但一旦你在空中就将其取下。

这些宏是否有可能成为语言?如果没有,有没有办法使用 Maven 运行像 m4 这样的预处理器?

谢谢。

4

4 回答 4

1

恕我直言,实现这一目标的“正确”方法是编写一个编译器插件来执行替换,但这真的值得付出那么多努力吗?

于 2010-08-03T12:16:13.630 回答
1

更新 @ralph好吧,这是2年前的一个问题,但是因为我对SCALA有同样的需求,__LINE__并且__FILE__您提到了SCALA;这是我的一些想法,使用 Scala 宏(从v2.10.0-RC1 开始

def $currentPosition:String = macro _currentPosition;
def _currentPosition(c:Context):c.Expr[String]={ import c.universe._;
  val pos = c.enclosingPosition;
  c.Expr(Literal(Constant(
    s"${pos.source.path}: line ${pos.line}, column ${pos.column}" )))
}

在编译时评估的宏被替换$currentPosition为描述其在源代码中的位置的文字字符串。例如,println在第 13 行输入 a,它会显示:

/sandbox/tmp_juno_workspace2/LogMacro_Test/src/test/Trial.scala: line 13, column 15

我没有广泛使用这些机制,但是通过调整它,可以开发他需要的日志记录功能(我应该补充一点,编写宏可能很困难 - 这对我来说!)。

于 2012-11-04T09:25:49.240 回答
0

无论如何,日志记录应该是一个跨领域的关注点。可以用方面做你想做的事。

于 2010-08-03T11:55:44.717 回答
0

您可以使用编译器 API 来执行此操作,但要小心。注释处理器/编译器插件的“规则”声明它们不应该修改正在生成的类。Sun/Oracle 可以随时强制执行此操作。

现在,看看http://projectlombok.org。它使用编译器 API 来生成 getter、setter 等。它们有你可以用作模型的源代码,或者你可以为它们提供处理程序。

您可能可以执行以下操作:

public class Foo {
  @FileName private static String fileName;
  @LineNumber private static int lineNumber;
  ...
  public void foo() {
     log(fileName, lineNumber, "some message");
  }
}

然后让注释处理器将 fileName 和 lineNumber 引用更改为实际的文件/行。

请注意,这可能会在以后的 JDK 版本中中断。我不知道 Sun/Oracle 是否真的会强制执行“不要修改正在生成的类”规则,但他们可以。

于 2010-08-04T14:54:35.267 回答