1

I am trying to create a Logger class in android , which would log message only if its a debug build.

object Logger2 {

private const val TAG = Constants.LOGGING_TAG

fun d(message : Any?){
    if (BuildConfig.DEBUG)
        Log.d(TAG , message.toString())
}

fun d(message: Any? , e : Exception?){
    if (BuildConfig.DEBUG)
        Log.d(TAG , message.toString(), e)
}
fun e(message : Any?){
    if (BuildConfig.DEBUG)
        Log.e(TAG , message.toString())
}

fun e(message: Any? , e : Exception?){
    if (BuildConfig.DEBUG)
        Log.e(TAG , message.toString(), e)
}

fun w(message : Any?){
    if (BuildConfig.DEBUG)
        Log.w(TAG , message.toString())
}

fun w(message: Any? , e : Exception?){
    if (BuildConfig.DEBUG)
        Log.w(TAG , message.toString(), e)
}

fun v(message : Any?){
    if (BuildConfig.DEBUG)
        Log.v(TAG , message.toString())
}

fun v(message: Any? , e : Exception?){
    if (BuildConfig.DEBUG)
        Log.v(TAG , message.toString(), e)
}

}

Since I want all of my other activities and classes to be able to use this logger class , I created the class as a kotlin object.

This works fine in all other kotlin classes ,I was able to call the log methods like this , This is how I call from the kotlin classes.

Logger2.e("message")

But from a Java class when I try to do the same call . I get this sort of error.

enter image description here

Can someone tell me what exactly does that error mean and how to fix it ? The method from which I am calling the Logger2 class is not even static . Then why this error ?

Saneen K P
  • 303
  • 1
  • 8
  • 2
    https://kotlinlang.org/docs/java-to-kotlin-interop.html#static-methods – IR42 Dec 01 '22 at 20:21
  • 1
    `The method from which I am calling the Logger2 class is not even static ` that is exactly what the error is complaining about. The `Logger2` method is not `static` but you are using it as if it was – Nexevis Dec 01 '22 at 20:22
  • @Nexevis how am I using it as if it was static ? is it because my kotlin class is an object ? – Saneen K P Dec 01 '22 at 20:27
  • 1
    This question should not have been closed as a duplicate of the Java questions about the error, because it has to do specifically with Kotlin `object`s and how they can be used from Java. – Tenfour04 Dec 01 '22 at 20:44

1 Answers1

6

Kotlin objects are not exactly equivalent to Java static. They are singletons. They exist as a class instance. When accessed from Java, the singleton instance must be retrieved through the static field named INSTANCE:

Logger2.INSTANCE.e("foo");

If you want the compiler to instead make each of these functions static so you don't have to retrieve them through the singleton instance, then mark them as @JvmStatic:

object Logger2 {

    @JvmStatic
    fun d(message : Any?){
        if (BuildConfig.DEBUG)
            Log.d(TAG , message.toString())
    } 

    //...
}

The documentation about this is here.

If you're curious about the reasons why it was designed this way:

  • The distinction between a Java class and its static members is sort of confusing. What do you even call the collection of static fields and methods of a Java class minus all the non-static members? It isn't any one thing.
  • Kotlin objects are flexible. They are an instance of a class just like any other class instance or function object or enum value, so you can pass them around as function arguments, and they can implement interfaces or be subclasses of other classes. They can be the receiver of extension functions. etc.
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • This has got to be the best answer I have received yet. Thanks a lot for mentioning every bit of the reasons and yes I was curious to understand the difference . Thanks a lot again. What do you mean by the function cannot rely on any non- \@JvmStatic members . Do you mean that I cannot call another non-\@JvmStatic function from a @Jvmstatic function of the same object ? – Saneen K P Dec 01 '22 at 21:06
  • Actually, I'm wrong about that. The real reason it's not automatic is that it compiles an additional overload of the method as a static method that calls through to the singleton instance method. – Tenfour04 Dec 01 '22 at 21:13
  • I am sorry , I did not understand . Could you please let me some reference or maybe an explanation. Thanks a lot again. – Saneen K P Dec 01 '22 at 21:24
  • The natural question you might have when you hear about `@JvmStatic` is, "Why isn't that done automatically? Why do we need to add an annotation?" The answer is that the static method is generated as additional code. It's adding overhead and size to the compiled bytecode, so this is omitted by default. – Tenfour04 Dec 01 '22 at 21:50