繁体   English   中英

寻找一种用Java编写调试print语句的简单方法

[英]Looking for an easier way to write debugging print statements in Java

编辑:我很想看看史蒂夫里德的AOP方法的反应。 鼓励回答他的回答!

我是新手,在某些时候我意识到在程序执行期间知道变量的内容会很有帮助。 所以我开始这样做:

编辑:修复此问题。 曾经是:var +“:”+ var,这是完全错误的。 愚蠢的错字。

System.err.println ( "var: " + var );

后来我才知道这是常见的做法。 至少,调试器不可用或不需要的地方。

我使用基本的文本编辑器,每次需要调试变量时键入print语句都很烦人,所以我想,为什么不是这样的:

void dbug ( Object obj )
{
    String variableName = obj.somehowGetVariableName();
    String variableContents = obj.toString();
    System.out.println ( variableName +": " + variableContents );
}

但显然得到变量名称说起来容易做起来难。

Java的反射如何对获得最名称对的一变量

我坚持:

System.err.println ( "var: " + var );

或者有一个流行的速记版本?

我不会尝试编写任何花哨的方法来打印出调试信息。 如果您使用的是记录器,请坚持使用LOG.debug(...)否则请坚持使用System.err.println(...)

您可能希望使用String.format("var=%s val=%s", "VarName", val)而不是String连接。

确保在每个类中重写toString方法以提供有意义的调试信息。

在一天结束时,通常更容易启动调试器并查看正在进行的操作,而不必跟踪已记录的调试行的负载。

我使用您的调试方法的唯一时间是,如果我的应用程序在地图中维护了所有状态,我可以轻松地打印出键值对(例如,Web应用程序中的会话映射)。

看看Simple Logging Framework ,它允许您输入:

class Example {
    static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(Example.class);

    void doSomething(Object obj1, Object obj2) {
        LOG.debug("This is object 1: {}, and this is object 2: {}", obj1, obj2);
    }
}

我认为System.err.format就是你想要的:

System.err.format("var: %s\n", var);

是一个简写:

System.err.println(String.format("var: %s", var));

一些想法:

  1. 我会在感兴趣的对象上实现toString() ,并以友好的方式打印成员(例如将时间戳转换为可读格式等)。 我通常会选择以下格式:

     Object[member1=,member2=...] 

    否则单独打印对象将为您提供类名加上身份哈希码,并且(正如您所发现的那样)并不是非常有用!

    Commons有自动执行此操作的工具。 但这是一个简单的toString() 教程 ,我觉得更合适。

  2. 您可能会对将来感兴趣的日志框架有所了解。 例如,查看Log4j 但是,目前我不担心这一点。

我个人并不建议在任何地方使用sysout语句。 您应该始终使用调试器(使用某些IDE)。 我无法想象这不会被通缉的地方。

否则我建议像log4j这样的日志记录框架,但是再次,这已经变得更加复杂,我将再次使用调试器切换到真正的IDE。

如果使用IntelliJ IDEA,可以使用“实时模板”快捷方式打印到System.out,例如soutp (and then a TAB)来调试方法参数, soutv用于跟踪变量的名称及其值,等等。

要读取快捷方式列表\\修改它,请转到文件 - >设置 - >实时模板 - >输出

我的第一个建议是:坚持使用java.util.logging包。 实际上不需要第三方日志库。

  1. 获取java.util.Logger的实例

    Logger logger = Logger.getLogger(“some.package.XyzClassName”);

  2. 记录对象(使用占位符{N})

    logger.log(Level.INFO,“logging stuff {0} and {1}”,new Object [] {new String(“Test”),1222});

在用户定义的类的情况下,您需要有一些明智的toString()重写实现,因为在消息{N}中替换占位符时会调用此方法。

您可以使用AOP和编译时编织来访问变量名称。 关于这一点的好处是,如果您不进行编织,则不会添加调试日志记录代码,因此您的运行时代码更精简,更快捷。

下面是一个使用AspectJ在字段设置为null时抛出异常的示例。 请注意使用“ joinPoint.getSignature() ”来访问代码元数据。

@Aspect
public class NotNullValidator {

   @Pointcut(value = "set(@com.acme.NotNull * *.*) && args(valueBeingSet)")
   private void setOfNonNullField(final Object valueBeingSet) { }

   @Before(value = "setOfNonNullField(valueBeingSet)")
   public void validate(final JoinPoint joinPoint, final Object valueBeingSet) {
      if (valueBeingSet == null) {
         throw new NullPointerException("Cannot set " + joinPoint.getSignature().getName() + " to null.");
      }
   }
}

请参阅JoinPoint Javadoc以查看您还可以获得的其他内容(行号,源和目标对象等)。

这是一段时间,但......

您将获得使用IDE而不是简单文本编辑器的建议。 100%,我赞同这一点。

您将获得使用日志框架或调试器而不是println()调用的建议。 嗯,当然,但......

更好的是单元测试。 不要问它是什么 - 告诉它你的期望。 然后,集成的单元测试框架(通常是junit)将验证您是否得到了您期望的结果。 我使用单元测试越多,我需要的调试就越少,而且我需要的println就越少。 当一些事情发生变化时,测试框架告诉我 - 我不需要手动重新评估每个测试的输出,只需看一下吧。

单元测试比调试好,比记录更好。 它们不是100%替代调试和日志记录,但是开始使用它们,你会发现对这些乏味活动的需求要少得多。

你试过DoodleDebug吗? 它是一个Eclipse插件,意味着像System.out.println()一样简单但功能更强大。

它可以在这里找到: http//scg.unibe.ch/wiki/projects/DoodleDebug

我建议你正确配置和使用Apache Log4J。 System.out或System.err行导致程序执行延迟很多。 (您可以通过添加一些时间信息来确认这一点,这些信息表明您的程序在没有System.out等的情况下需要多长时间以及没有这些行的情况。

日志API使用单独的线程在日志文件中记录日志信息,这就是为什么它们在实际应用程序中更有用。 此外,Log4J等日志记录API可以很好地控制如何配置和格式化日志。 例如,在这里查看从Log4J生成的一些日志:

2012-01-05 15:16:41,730 [main] 16   DEBUG dmfssecbuild.IOUtil  - 
2012-01-05 15:16:41,730 [main] 16   DEBUG dmfssecbuild.IOUtil  - Application Configs Loaded
2012-01-05 15:16:41,730 [main] 16   DEBUG dmfssecbuild.Constants  - Running Application between dates.
2012-01-05 15:16:41,730 [main] 16   DEBUG dmfssecbuild.Constants  - Sat Jan 01 00:00:00 GMT+05:00 2011 From Date 
2012-01-05 15:16:41,730 [main] 16   DEBUG dmfssecbuild.Constants  - Mon Dec 31 00:00:00 GMT+05:00 2012 To Date 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM