我知道Java中预处理器和宏的所有哲学论据。我不同意,因为有些人可能会滥用语言功能,所以应该排除所有语言功能。
我想在我的Java和Scala代码中包含__FILE__
和__LINE__
宏,以实现高效的日志记录。由于运行时性能的影响,任何使用Exception都是不可接受的。那些认为可以在“生产代码”中关闭日志记录的人应该听取Brian Kernighan的建议:
删除错误消息“现在程序正在运行”就像在地上戴降落伞一样,但是一旦你在空中就把它取下来。
这些宏是否有可能使其成为语言?如果没有,有没有办法使用Maven运行像m4这样的预处理器?
感谢。
答案 0 :(得分:1)
恕我直言,实现这一目标的“正确”方法是编写一个编译器插件来执行替换,但是真的值得付出这么多努力吗?
答案 1 :(得分:1)
<强>更新强>
@ralph
嗯,这是2年多以前的一个问题,但由于我对__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
被替换为描述其在源代码中的位置的文字字符串。例如,在第13行放入println
,它会显示:
/sandbox/tmp_juno_workspace2/LogMacro_Test/src/test/Trial.scala: line 13, column 15
我没有广泛使用这些机制,但通过调整这个东西,可以开发他需要的日志记录功能(我应该补充一点,编写宏可能很困难 - 这对我来说!)。
答案 2 :(得分:0)
无论如何,记录应该是一个贯穿各领域的问题。可以用方面做你想做的事。
答案 3 :(得分: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是否会实际执行“不要修改正在生成的类”规则,但他们可以。