为什么在Android中不应使用System.out.println()?

24
Android开源项目的代码风格中,规定不应该使用System.out.println(),但是我不明白为什么。有人能解释一下吗?我应该使用什么来跟踪我的应用程序日志?
以下是参考行:

System.out.println()(对于本地代码使用printf())不应该被使用。 System.outSystem.err会被重定向到/dev/null,所以你的打印语句将没有任何可见效果。然而,所有这些调用发生的字符串构建都会被执行。


这个建议只针对 Android 源码吗? - Zhou Hongbo
7个回答

35

您应该使用android.util.Log类。

以下是Log类的描述:

用于发送日志输出的API。

通常,您应该使用Log.v()Log.d()Log.i()Log.w()Log.e()方法来编写日志。然后,您可以在logcat中查看日志

从最不详细到最详细的记录级别顺序为ERROR、WARN、INFO、DEBUG、VERBOSE。Verbose除了在开发期间外,永远不应该编译进应用程序中。调试日志在编译时被编译进去,但在运行时被剥离。错误、警告和信息日志始终保留。

这些是Log类的可用方法:

  1. Log.d() - 发送一个DEBUG日志信息。
  2. Log.e() - 发送一个ERROR日志信息。
  3. Log.i() - 发送一个INFO日志信息。
  4. Log.v() - 发送一个VERBOSE日志信息。
  5. Log.w() - 发送一个WARN日志信息。
  6. Log.wtf() - 糟糕的失败:报告一个永远不应该发生的异常。
上述方法(除了Log.wLog.wtf,它们有3种可能的参数模式)需要以下参数:
  1. String tag, String msg

    tag:用于标识日志消息的来源。此值可以为null

    msg:您想记录的消息。此值可以为null

  2. String tag, String msg, Throwable tr - 与第一种模式类似,但允许指定异常。如果要将异常记录到日志输出中,则应使用此模式。

  3. (对于Log.wLog.wtf) String tag, Throwable tr - 与第三种模式类似,但不允许指定消息。请注意,仍然可以传递消息,但应该在第二个参数排列中。


编辑: 直接回答您的问题: System.outSystem.errprintln()仍将在logcat中显示,但有限制。

  • 您不能使用System.outSystem.err记录VERBOSEERRORDEBUG
  • 您不能定义自己的标签,它将显示带有您文本的System.errSystem.out。例如:

    • System.out.println("Hello!")等同于Log.i("System.out","Hello!")
    • System.err.println("Hello!")等同于Log.w("System.err","Hello!")

7
Log.wtf() 显然意味着“非常糟糕的失败”(http://developer.android.com/reference/android/util/Log.html#wtf%28java.lang.String,%20java.lang.Throwable%29) - nulldev

3

System.out.println("")在Android中不会正常运行,因为应用程序没有连接到终端。

最好使用Log.(d)(v)(e)(i)(w),因为有些东西正在主动监视LogCat。

System.out.println()会将内容打印到LogCat中,但需要额外的一组系统指令,使其效率不高,但它仍然有效。


2

如果我们想跟踪 Android 项目,我们可以使用 Log 类。它有一些方法,例如:
Log.e(TAG,MESSAGE)
Log.v(TAG,MESSAGE)
Log.w(TAG,MESSAGE)
Log.d(TAG,MESSAGE)
Log.i(TAG,MESSAGE)
它是 Utils 包的静态方法。将它逐行放置,您可以在 LogCat 中查看它。
享受 Android 的乐趣吧!


1

从你自己的链接中可以看到:

不应使用System.out.println()(或原生代码的printf())。 System.out和System.err将被重定向到/ dev / null,因此您的打印语句将没有可见效果。 但是,所有针对这些调用进行的字符串构建仍将被执行。

此外,在该页面的开头,它说:

以下规则不是指南或建议,而是严格的规则。 如果Android的贡献不遵守这些规则,则通常不会被接受。

所以不要这样做!


10
这个回答如何回应“为什么”的问题? - LarsH
@LarsH,我认为这里已经有足够的原因了。我没有添加任何关于为什么的内容,只是重复了Android所说的。在我看来,这很清楚。它没有可见的影响,但仍然需要处理时间。如果我漏掉了什么,那就是“如何”,也就是他们应该使用什么来记录日志。等我有时间时,我会补充这一点。 - ChiefTwoPencils
是的,安卓文档中的第一条引言解释了为什么,而那个引言也是原始问题的一部分。你的回答只添加了另一个引言,说“不要这样做!”,但并没有提供任何原因。因此我的评论。不过你说得对,OP基本上也询问了“如何”。当然你可以补充一些关于它的内容,但我认为其他答案已经很好地涵盖了它(即使用Log.*())。 - LarsH
1
它确实起作用吗?也许是在没人注意的情况下悄悄地添加到框架中的?我有一个新手开发者在为我工作,他在我还没来得及阻止他之前就把几个System.out.println()调用扔进去了,在LogCat(Eclipse)中完美地显示出来,不需要“标签”参数。 - William T. Mallard
@WilliamT.Mallard,是的,确实如此。昨天我看到一篇帖子声称他们在异常中没有看到任何来自System.out.println语句的输出,我说-这是一种可靠的调试Android的方式吗...他们说对他们来说很好用。据我所知,它现在被重新路由通过Log.i,但我猜可能不比上面的方法更可靠... - ChiefTwoPencils

1
你可以使用内置的日志工具,直接在LogCat中打印出来。
对于错误,可以使用Log.e(String, String),它将以红色显示。还有vdiw,分别用于详细信息、调试、信息和警告。

1
以下代码可以打印出异常信息:
1. Log.d("myapp", Log.getStackTraceString(new Exception()));
或者,您可以通过深入挖掘来获得更长的堆栈跟踪。例如:

Log.getStackTraceString(e.getCause().getCause());


1
日志是跟踪我们的Android项目的最佳方式,就像以下代码一样...它将帮助您...只需查看DDMS logCat,了解项目的构建情况即可...要求...使用android.utils.Log;包。
@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    for(int i=0;i<100;i++)
    {
        Log.e("i = ",""+i);
        Log.v("i = ",""+i);
        Log.i("i = ",""+i);
        Log.w("i = ",""+i);
        Log.d("i = ",""+i);
    }
}
我希望这对您有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接