当前位置 主页 > 网站技术 > 代码类 >

    Java里的static在Kotlin里如何实现

    栏目:代码类 时间:2020-01-06 18:05

    static修饰符是java里面非常常用的一个东西,用法也非常多。然而,在kotlin里竟然没有这个东西!那该如何替代呢?本文就总结了下java里面static的几种常见用法在kotlin里的替代方式。

    static在java里面的用法总结

    static在java里面的用法有很多,最常用的有下面几种:

    静态变量及方法 静态初始化 静态内部类

    下面我们就看看这几种场景在kotlin是如何实现的。

    场景一:静态变量及方法

    静态变量及方法可能是我们平时用到static最多的地方,我们先看看java里面是如何做的。

    java静态变量及方法介绍:

    首先,是静态变量和方法的定义:

    public class StaticTest {
      public static int STATIC_VAR = 0;
    
      public static void staticMethod(String str){
        System.out.println(str);
      }
    }
    
    

    然后是静态变量和方法的使用:

    StaticTest.STATIC_VAR = 10;
    StaticTest.staticMethod("hello");
    

    java的实现方式大家都非常熟悉了,下面着重说说kotlin是如何实现的。

    kotlin替代静态变量及方法的方案

    kotlin通过引入“伴生对象”的概念来替代java里的静态变量及方法。

    “伴生对象”这个名词听上去很古怪,其实非常简单:在类的内容使用companion来标记一个对象。所有需要“静态化”的变量和方法都放在这个对象里。

    下面是定义伴生对象的代码:

    class StaticTest {
      companion object{//伴生对象是可以指定名字的,不过一般都省略掉。
        var STATIC_VAR = 0
    
        fun staticMethod(str: String?) {
          println(str)
        }
      }
    }
    
    

    接下来看看如何使用伴生对象,伴生对象只能通过类名来访问,使用方法和java差不多:

    StaticTest.STATIC_VAR = 100
    StaticTest.staticMethod("hello")
    

    kotlin的伴生对象解决了什么问题?

    大家可能会好奇,为什么kotlin要用这么一个奇怪的方式来解决这个问题呢?

    我的理解是有两个原因:

    第一,使用伴生对象体现了kotlin一贯的设计理念:一切都是对象!伴生对象也是对象!而java的static,显然和对象没有关系。

    第二,伴生对象解决了java静态变量及方法的一个常见的反模式:静态方法及变量可以通过对象的引用来访问。

    还是拿上面的例子,java的静态变量及方法可以通过类引用和对象引用两种方法访问:

    //通过类引用访问
    StaticTest.STATIC_VAR = 10; 
    StaticTest.staticMethod("hello");
    
    //通过对象引用访问
    StaticTest obj = new StaticTest();
    obj.STATIC_VAR = 10;
    obj.staticMethod("hello");
    
    

    而通过对象引用访问静态变量及方法,显然是不合适的。但是在java里却没有办法从语法层面避免这个问题。

    而kotlin的伴生对象只能通过类引用访问,从语法的层面解决了这个问题:

    //使用类引用访问
    StaticTest.STATIC_VAR = 100
    StaticTest.staticMethod("hello")
      
    //不能使用对象引用访问
    val obj = StaticTest()
    obj.STATIC_VAR = 100 //编译错误
    obj.staticMethod("hello") //编译错误
    

    总之,kotlin里每个新的语言特性,都是为了填补java的某一个坑。

    场景二:静态初始化

    java里的静态初始化可以在类加载的时候初始化一些静态变量,比如:

    public class StaticTest {
      public static int STATIC_VAR = 0;
      
      static {
        STATIC_VAR = 100;
        System.out.println("in static init");
      }
      
      public static void main(String[] args) {
        System.out.println(StaticTest.STATIC_VAR);
      }
    }