Kotlin实现静态方法与静态变量的两种方式

5,647 阅读3分钟

1. 新建.kt文件(不是Class等), 直接在kt文件中写方法

示例Utils.kt

@file:JvmName("Utils")
package com.demo.android.utils

import android.util.Log

const val TAG = "Utils"
var msg = "This is a static function"

fun staticFun() {
    Log.d(TAG, msg)
}

我们可以通过Android Studio中的Tools -> kotlin -> Show Kotlin Bytecode -> Decompile到java代码查看

package com.demo.android.utils;

import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class Utils {
   @NotNull
   public static final String TAG = "Utils";
   @NotNull
   private static String msg = "This is a static function";

   @NotNull
   public static final String getMsg() {
      return msg;
   }

   public static final void setMsg(@NotNull String var0) {
      Intrinsics.checkParameterIsNotNull(var0, "<set-?>");
      msg = var0;
   }

   public static final void staticFun() {
      Log.d("Utils", msg);
   }
}

我们可以看到Java代码是生成了一个名为UtilsKt的Class文件, 而staticFun就是一个静态方法了, TAG就是一个静态常量, msg也就是一个静态变量. 当我们加上@file:JvmName("Utils")的注解, 然后生成的Java类名也就是Utils了.

###在Kotlin或者Java代码中调用

  1. 在kotlin中调用

    package com.demo.android
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import com.demo.android.utils.staticFun
    
    class DemoActivity: AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            staticFun()
        }
    }
    

    在kotlin中调用的话, 是无法使用class.fun的方式的, 只能直接引用方法名, import的也是方法名

    反编译成java

    package com.demo.android;
    
    import android.os.Bundle;
    import android.view.View;
    import androidx.appcompat.app.AppCompatActivity;
    import com.demo.android.utils.Utils;
    import java.util.HashMap;
    import kotlin.Metadata;
    import org.jetbrains.annotations.Nullable;
    
    public final class DemoActivity extends AppCompatActivity {
    
       protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Utils.staticFun();
          // 如果不增加@file:JvmName("Utils")的注解
         	// UtilsKt.staticFun()
       }
    }
    
  2. 在java中调用就跟上方反编译成java一样

2. 在objects或者companion objects中加上@JvmStatic的注解

Utils.kt

@file:JvmName("Utils")
package com.demo.android.utils

import android.util.Log

object Utils {
    const val TAG = "Utils"
    var msg = "This is a static function"

    fun staticFun() {
        Log.d(TAG, msg)
    }
}

反编译成java

package com.vova.android.utils;

import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class Utils {
   @NotNull
   public static final String TAG = "Utils";
   @NotNull
   private static String msg;
   public static final Utils INSTANCE;

   @NotNull
   public final String getMsg() {
      return msg;
   }

   public final void setMsg(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      msg = var1;
   }

   public final void staticFun() {
      Log.d("Utils", msg);
   }

   private Utils() {
   }

   static {
      Utils var0 = new Utils();
      INSTANCE = var0;
      msg = "This is a static function";
   }
}

在单例类Utils中, 我们可以看到所有的变量都是静态变量, 而方法在没有@JvmStatic的注解时, 不是静态方法,

变量msgget() set()方法也不是静态方法

增加@JvmStatic注解

@file:JvmName("Utils")
package com.demo.android.utils

import android.util.Log

object Utils {
    const val TAG = "Utils"
    @JvmStatic
    var msg = "This is a static function"

    @JvmStatic
    fun staticFun() {
        Log.d(TAG, msg)
    }
}

反编译成java

package com.demo.android.utils;

import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.JvmStatic;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class Utils {
   @NotNull
   public static final String TAG = "Utils";
   @NotNull
   private static String msg;
   public static final Utils INSTANCE;

   /** @deprecated */
   // $FF: synthetic method
   @JvmStatic
   public static void msg$annotations() {
   }

   @NotNull
   public static final String getMsg() {
      return msg;
   }

   public static final void setMsg(@NotNull String var0) {
      Intrinsics.checkParameterIsNotNull(var0, "<set-?>");
      msg = var0;
   }

   @JvmStatic
   public static final void staticFun() {
      Log.d("Utils", msg);
   }

   private Utils() {
   }

   static {
      Utils var0 = new Utils();
      INSTANCE = var0;
      msg = "This is a static function";
   }
}

增加@JvmStatic注解后, 我们可以看到staticFun()与变量msgget() set()也都是静态方法了

**companion objects**同理

在Kotlin或者Java代码中调用

  1. 在kotlin中调用

    package com.demo.android
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import com.demo.android.utils.Utils
    
    class DemoActivity: AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Utils.staticFun()
          	Utils.msg
        }
    }
    

    反编译成java

    package com.vova.android;
    
    import android.os.Bundle;
    import android.view.View;
    import androidx.appcompat.app.AppCompatActivity;
    import com.vova.android.utils.Utils;
    import java.util.HashMap;
    import kotlin.Metadata;
    import org.jetbrains.annotations.Nullable;
    
    public final class DemoActivity extends AppCompatActivity {
    
       protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Utils.staticFun();
          Utils.getMsg();
       }
    
    }
    

    在java中调用与反编译成java相同

总结

在java中我们写工具类时, 通常都是使用静态方法来实现, 而在kotlin中, 通常是使用object类,

而object类就是一个单例, 相对于直接引用静态方法总会new一个对象.

上面介绍的静态方法, 第一种其实与我们平时在java中实现相同, 但是引用方式不同, 所以我现在更喜欢在kotlin项目中使用object来写工具类