我正在编写一个从文件中读取结构的程序。出于调试目的,如果我可以使用编译时切换来打印所有读取的名称和值,这可以被禁用,以便在生产版本中获得更好的性能/代码大小,这将非常方便。在C中,我可以像这样使用预处理器来实现这个目的:
#ifdef DEBUG
#define READ(name, in) { name = read(in); printf("#name: %d\n", name); }
#else
#define READ(name, in) { name = read(in); }
#endif
void myreader(mystream_t *in)
{
int a, b, c;
READ(a, in);
READ(b, in);
READ(c, in);
}
有什么方法可以重现这个结构吗?我想到了这个:
private static final boolean DEBUG_ENABLED = true;
private int debugRead(MyInputStream in, String name) {
int val = in.read();
if (DEBUG_ENABLED) {
System.out.println(String.format("%s: %d", name, val));
}
return val;
}
public MyReader(MyInputStream in) {
int a, b, c;
a = debugRead(in, "a");
b = debugRead(in, "b");
c = debugRead(in, "c");
}
但是,这要求我输入两次所有变量的名称,以及存储与发布版本相对应的所有名称的字符串。有更好的方法吗?
编辑:我最担心的是代码冗长。我想要的最后一件事就是让我的代码混乱,调试/打印/跟踪语句会掩盖实际的读取逻辑。答案 0 :(得分:0)
我不确定这是否是苹果对苹果解决方案,但Java中惯用的一件事是使用日志框架。有了它,您可以在需要调试的任何地方执行log.debug
。 SLF4j是日志框架的通用外观。您可以将它与JUL日志记录一起使用。
通常您将日志记录代码留在那里,并在外部配置记录器以打印或不打印消息。
如果您正在使用SLF4j,则调试消息将如下所示:
log.debug("Setting the creation timestamp to {}", timestamp);
大多数记录器可以配置为告诉您日志消息来自哪个时间,类和方法。
与您习惯的相比,这有一些优点和缺点。
System.out.println
,这需要付出很多努力。
答案 1 :(得分:0)
对于在Java中模拟C / C ++宏的一般问题,有几种解决方案。记录的特殊情况通常以更简单的方式解决。最简单,概念最接近,最纯粹的形式是在界面中抽象宏并产生替代实现:
public class Sample {
class mystream_t {
}
public int read(mystream_t is) {
return 0 ;
}
static final boolean DEBUG= false ;
interface ReadType {
public void apply(int[] name,mystream_t in);
}
ReadType READ; {
if( DEBUG ) {
READ= new ReadType(){
public void apply(int[] name,mystream_t in) {
name[0]= read(in) ; System.out.printf("#name: %d\n",name);
}
};
} else {
READ= new ReadType(){
public void apply(int[] name,mystream_t in) {
name[0]= read(in) ;
}
};
}
}
void myreader(mystream_t in) {
int[] a= new int[1], b= new int[1], c= new int[1];
READ.apply(a, in);
READ.apply(b, in);
READ.apply(c, in);
}
}
这使用了一种简单的静态代码注入形式。我试图使代码尽可能接近原始代码。
在Java中模拟C / C ++宏的第二个最相关的方法需要注释和注释处理。它更接近C / C ++宏,但需要更多的努力,并采用一种不能被视为语言纯粹部分的机制。
第三个是使用AspectJ等面向方面的编程框架。