Kotlin基本语法之(七) 静态成员与companion伴生对象

2,795 阅读2分钟

Kotlin的静态实现

在Java中可以通过static关键字声明静态的属性或方法。但是在Kotlin中并没有延续这个关键字,而是使用伴生对象实现,在class内部声明一个companion object代码块,其内部的成员变量和方法都将被编译为静态的。

class TestStatic {
    //伴生对象
    companion object Factory {
        val str: String = ""
        fun create(): TestStatic {
            println(this)
            return TestStatic()
        }
    }
}

Factory为最终生成的静态内部类类名,通常来说Factory名字可以省略,如果省略,类名为默认的Companion。

调用方法,就跟调用一个静态方法一样类名+方法名。

TestStatic.create()

静态代码块

Kotlin中的也可写静态代码块,只需在companion object中嵌套一个init代码块。

companion object {
    //静态代码块
    init {
        val a = "adc"
    }
}

反编译代码后可以看到与java中的写法一致。

static {
  String var0 = "adc";
}

与内部object类的区别

通过反编译我们可以看一下其内部实现。

public final class TestStatic {
   //静态成员变量
   private static final String str = "";
   public static final TestStatic.Factory Factory = new TestStatic.Factory();

   public static final class Factory {
      @NotNull
      public final String getStr() {
         return TestStatic.str;
      }

      @NotNull
      public final TestStatic create() {
         System.out.println(this);
         return new TestStatic();
      }

      private Factory() {
      }
   }
}

是不是感觉和上一篇讲的object类有点像?其实还真是挺像的,因为就差一个关键字,我们把companion关键字去掉,重新反编译对比一下。

class TestStatic {
    object Factory {
        val str: String = ""
        fun create(): TestStatic {
            println(this)
            return TestStatic()
        }
    }
}

反编译结果:

public final class TestStatic {
   
   public static final class Factory {
      //成员变量声明在内部类中
      private static final String str = "";
      public static final TestStatic.Factory INSTANCE;

      @NotNull
      public final String getStr() {
         return str;
      }

      @NotNull
      public final TestStatic create() {
         System.out.println(this);
         return new TestStatic();
      }

      private Factory() {
      }

      static {
         TestStatic.Factory var0 = new TestStatic.Factory();
         INSTANCE = var0;
         str = "";
      }
   }
}

通过代码的比较发现了明显的区别,虽然两者最终都会生成一个静态内部类,但companion object代码块中的成员变量最终会被声明到外部类中,也这是为什么我们能通过外部类名直接访问,而object类则需要用外部类.内部类的方式调用。

//object类调用方式
TestStatic.Factory.create()
//companion object代码块使用方式
TestStatic.create();//编译器会我们自动补全为TestStatic.Factory.create()

注意事项

  1. 一个类中最多只能有一个companion object代码块
  2. 伴生对象本质上就是一个静态内部类,所以它还能继承其他类,下面的写法也是可以的。
companion object : Comparable<String> {
    override fun compareTo(other: String): Int {
        //支持比较
    }
}