Java 在 Kotlin 中定义日志 TAG 常量的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45841067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to define log TAG constant in Kotlin?
提问by Mario Kutlev
I'm creating my first Kotlin classes in my Android application. Usually for logging purposes I have a constant with name TAG
. What I would do in Java is:
我正在我的 Android 应用程序中创建我的第一个 Kotlin 类。通常出于记录目的,我有一个名为 name 的常量TAG
。我会在 Java 中做的是:
private static final String TAG = MyClass.class.getSimpleName();
I know that in Kotlin classes I can create TAG
using this way:
我知道在 Kotlin 类中我可以TAG
使用这种方式创建:
private val TAG = MyClass::class.java.simpleName
This is OK for projects that use Java and Kotlin but what if I start a new project that is only in Kotlin? How can I define there TAG
constant? Is there more Kotlin way where I don't have this strange construction class.java.simpleName
?
这对于使用 Java 和 Kotlin 的项目没问题,但是如果我开始一个仅使用 Kotlin 的新项目怎么办?我如何定义TAG
常量?有没有更多的 Kotlin 方式让我没有这种奇怪的结构class.java.simpleName
?
采纳答案by Gabriele Mariotti
In general constants are all caps (ex. FOO) and located in the companion object:
一般来说,常量都是大写的(例如 FOO)并位于伴随对象中:
class MyClass {
companion object {
public const val FOO = 1
}
}
and to define the TAG field you can use:
并定义您可以使用的 TAG 字段:
private val TAG = MyClass::class.qualifiedName
回答by Matias Elorriaga
I'm creating the constant as a companion object:
我正在创建常量作为伴随对象:
companion object {
val TAG = "SOME_TAG_VALUE"
}
Then, I can use it like this:
然后,我可以像这样使用它:
MyClass.TAG
回答by Gabriele Mariotti
Declare of TAG variable with val
用 TAG 变量声明 val
class YourClass {
companion object {
//if use java and kotlin both in project
//private val TAG = MyClass::class.java.simpleName
//if use only kotlin in project
private val TAG = YourClass::class.simpleName
}
}
Use the variable like
使用变量,如
Log.d(YourClass.TAG, "Your message");
//or
Log.e(TAG, "Your message");
回答by jpihl
I found a way which is more "copy-paste"-able, since it doesn't require you to type the name of your class:
我找到了一种更“复制粘贴”的方法,因为它不需要您输入类的名称:
package com.stackoverflow.mypackage
class MyClass
{
companion object {
val TAG = this::class.toString().split(".").last().dropLast(10)
}
}
It's not the most elegant solution but it works.
这不是最优雅的解决方案,但它有效。
this::class.toString().split(".").last()
will give you "com.stackoverflow.mypackage.MyClass$Companion"
so you need the dropLast(10)
to remove $Companion
.
this::class.toString().split(".").last()
会给你"com.stackoverflow.mypackage.MyClass$Companion"
所以你需要dropLast(10)
删除$Companion
。
Alternatively you can do this:
或者你可以这样做:
package com.stackoverflow.mypackage
class MyClass
{
val TAG = this::class.simpleName
}
But then the TAG
member variable is no longer "static" and doesn't follow the recommended naming conventions.
但是TAG
成员变量不再是“静态的”并且不遵循推荐的命名约定。
回答by Fredy Mederos
AnkoLoggeruses an interface to define the log tag.
AnkoLogger使用一个接口来定义日志标签。
interface AnkoLogger {
/**
* The logger tag used in extension functions for the [AnkoLogger].
* Note that the tag length should not be more than 23 symbols.
*/
val loggerTag: String
get() = getTag(javaClass)
}
private fun getTag(clazz: Class<*>): String {
val tag = clazz.simpleName
return if (tag.length <= 23) {
tag
} else {
tag.substring(0, 23)
}
}
inline fun AnkoLogger.info(message: () -> Any?) {
val tag = loggerTag
if (Log.isLoggable(tag, Log.INFO)) {
Log.i(tag, message()?.toString() ?: "null")
}
}
You can use it like this:
你可以这样使用它:
class MyClass : AnkoLogger {
fun someFun(){
info("logging info")
}
}
Maybe AnkoLogger can give you some ideas to implement a custom logging tool.
也许 AnkoLogger 可以给你一些实现自定义日志工具的想法。
回答by Andrew Wang
You can define your TAG
by @JvmField
as below:
你可以定义你TAG
的@JvmField
如下:
companion object {
@JvmField val TAG: String = MyClass::class.java.simpleName
}
For more details, you can read this article : Kotlin's hidden costs
更多细节可以阅读这篇文章:Kotlin 的隐性成本
回答by Kasim Rangwala
Updated answer with Kotlin 1.2.20
更新了答案 Kotlin 1.2.20
class MyClass {
companion object {
@JvmField
public val FOO = 1
}
}
uses
用途
MyClass.FOO
回答by Yaroslav Mytkalyk
Commonly suggested approach of using the companion object
generates extra static final
instance of a companion class and thus is bad performance and memory-wise.
通常建议的使用companion object
生成static final
伴随类的额外实例的方法,因此性能和内存都很差。
The best way (IMHO)
最好的方式(恕我直言)
Define a log tag as a top-level constant, thus only extra class is generated (MyClassKt
), but compared to companion object
there will be no static final
instance of it (and no instance whatsoever):
将日志标签定义为顶级常量,因此只会生成额外的类 ( MyClassKt
),但相比之下,companion object
将没有static final
它的实例(也没有任何实例):
private const val TAG = "MyLogTag"
class MyClass {
fun logMe() {
Log.w(TAG, "Message")
}
}
Another option
另外一个选项
Use a normal val
. Though this looks unusual to see a log tag not as an all-uppercase constant, this will not generate any classes and has least overhead.
使用正常的val
. 尽管看到日志标记不是全大写的常量看起来很不寻常,但这不会生成任何类并且开销最小。
class MyClass {
private val tag = "myLogTag"
fun logMe() {
Log.w(tag, "Message")
}
}
回答by nickgzzjr
Simply doing the following worked for me.
简单地做以下工作对我有用。
private val TAG = this::class.java.simpleName
回答by Paolo
I created some Log extension functions to avoid declaring the log tag as we did in Java (maybe less performant, but given that we are talking about logging this should be acceptable IMO). The approach uses reified type parameters and other Kotlin goodies to retrieve the class simple name. Here is a basic example:
我创建了一些日志扩展函数来避免像我们在 Java 中所做的那样声明日志标记(可能性能较低,但考虑到我们正在谈论日志记录,这应该是可以接受的 IMO)。该方法使用具体化的类型参数和其他 Kotlin 好东西来检索类的简单名称。这是一个基本示例:
inline fun <reified T> T.logi(message: String) =
Log.i(T::class.java.simpleName, message)
You can find a more elaborated gist here
你可以在这里找到更详细的要点