kotlin特性之object、apply用法总结 - Xiasm/Java-Android-Learn GitHub Wiki

前言

最近试用了下kotlin,因为也是一个在jvm执行的静态语言,所以快速熟悉了下语法就直接用了。但是用的过程中,还是有些地方花费了很长时间才理解。仅此记录下来

object关键字

object是kotlin中一个很重要的关键字,java中没有。object关键字直译过来就是“对象”,object关键字用法有很多种,如对象声明、伴生对象、对象表达式等。我们先来从最简单的看:

  • 对象声明

我们先来写一个object修饰的类,然后转成java代码看一下:

object Test {

    fun hello() {

    }
}

这是一个object修饰的类,使用object关键字后就不能再使用class关键字了。我们用as的工具将其转换为java代码如下:

public final class Test {
   public static final Test INSTANCE;

   public final void hello() {
   }

   static {
      Test var0 = new Test();
      INSTANCE = var0;
   }
}

生成的java代码可以看出,这是一个final修饰的类,并且在加载类的时候实例化出一个对象INSTANCE,你大概隐隐猜出了这个object关键字代表着什么含义吧!
对的,如果你用object声明一个类,这个类就是一个“单例的类”。如果你在AndroidStudio中打算继承此类,会飘红报错“Cannot inherit from a singleton”,即不能继承一个单例,从java代码中也可以看出。
做下总结:object关键字声明一个类,这个类就是单例的,不能再创建实例,并且没有构造器,调用的时候有以下两种方法:

//直接类名调用
Test.hello()

//赋给一个常量,再调用
val a : Test = Test
a.hello()
  • 伴生对象(Companion object)

在用kotlin的时候,我发现kotlin中没有static关键字,那么如何来表示出static的效果呢?我还以一个例子来解释:

class Test1 {
    companion object CO {
        val filed : String = "I'm in companion object"

        fun coHello(){
            println(filed)
        }
    }
    fun hello() {
        println("I'm Test1")
    }
}

转成java代码后:

public final class Test1 {
   @NotNull
   private static final String filed = "I'm in companion object";
   public static final Test1.CO CO = new Test1.CO((DefaultConstructorMarker)null);

   public final void hello() {
      String var1 = "I'm Test1";
      System.out.println(var1);
   }

   @Metadata(
      mv = {1, 1, 11},
      bv = {1, 0, 2},
      k = 1,
      d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0007\u001a\u00020\bR\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\t"},
      d2 = {"Lorg/doubleprotein/mathilda/notes/Test1$CO;", "", "()V", "filed", "", "getFiled", "()Ljava/lang/String;", "coHello", "", "app"}
   )
   public static final class CO {
      @NotNull
      public final String getFiled() {
         return Test1.filed;
      }

      public final void coHello() {
         String var1 = ((Test1.CO)this).getFiled();
         System.out.println(var1);
      }

      private CO() {
      }

      // $FF: synthetic method
      public CO(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

可以看得出,伴生对象类似于java中的静态内部类,并且在Test1中会持有一个伴生对象的实例,我们在调用伴生对象的方法时,有以下两种调用方式:

//方式1
Test1.CO.coHello()

//方式2
Test1.coHello()

//调用属性
Test1.filed

效果是不是跟java中调用static方法或属性很相似。当然kotlin中替代static关键字特性的东西不止半生对象一个,还有一个包级别函数也可以用来替代。

apply

apply函数的返回值是本身,在函数内部,你可以任意调用对象的属性或方法或给属性赋值等!我们还是通过例子来看:

class People {
    var eye : Int = 2

    var leg : Int = 2

    fun hello() {
        println("eyes=" + eye + ", legs=" + leg)
    }
}

定义Peoplele类,然后创建实例,并调用它的apply方法:

fun test() {
    val p = People()

    p.apply {
        eye = 3
        hello()
        leg = 5
    }.hello()

    p.hello()
}

我们看转换成的java代码:

public final void test() {
   People p = new People();
   p.setEye(3);
   p.hello();
   p.setLeg(5);
   p.hello();
   p.hello();
}

由java代码也可以看出,apply函数极大的简化了给对象赋值等操作,并且会将自身返回。kotlin的这些语法糖还是很有意思的!

⚠️ **GitHub.com Fallback** ⚠️