美文网首页DevSupportKotlin
kotlin之object,companion object,内

kotlin之object,companion object,内

作者: _非_阳_ | 来源:发表于2019-11-13 16:55 被阅读0次

    最近开始使用kotlin写项目了,这几天一直对object,companion object,内部类inner class搞得有点迷糊

    现在抽空,理清一下他们之间区别

    我定义了一个class A
    然后再class A内部分别定义了class B,object C,companion object D,inner class E四中不同的类
    每个类中包含一个字段和一个函数

    /**
     * Copyright:AndroidInterview
     * Author: liyang <br>
     * Date:2019-11-12 14:29<br>
     * Desc: <br>
     */
    class A  {
        var sex = "男"
        val age = 11
        val a1:String="nan"
        val a: String
            get() {
                return when (sex) {
                    "男" -> "man"
                    else -> "women"
                }
            }
    
        fun a() {
            //class B
            //在A类中调用class B的b方法
            val b = B()
            b.b()
            b.b
            
            //inner class E
            //在A类中调用inner class E的e变量和e()方法
            val e=E()
            e.e
            e.e()
    
            //object C
            //在A类中调用object C的c()方法和c变量
            C.c()
            C.c
    
            //companion object D
            //可以直接在A类中调用伴生类的d()方法和d变量
            d()
            d
        }
    
        class B {
            val b = "b"
            fun b() {
                println("b() is invoked")
            }
        }
    
        object C {
           const val c = "c"
            fun c() {
                println("c() is invoked")
            }
        }
    
    
        companion object D {
            val d = "d"
    
            fun d() {
                println("d() is invoked")
            }
        }
    
        inner class E {
            val e = "e"
            fun e() {
                println("e() is invoked")
            }
        }
    
    
    }
    

    接下来在main方法中调用它们,看看调用的时候有什么不同

    /**
     * Copyright:AndroidInterview
     * Author: liyang <br>
     * Date:2019-11-12 14:29<br>
     * Desc: <br>
     */
    open class Outer {
        companion object {
            @JvmStatic
            fun main(args: Array<String>) {
                val a = A()
                a.a
                a.a()
    
                //内部类
                val b = A.B()
                println(b.b)
                b.b()
    
                //inner class
                val e = a.E()
                println(e.e)
                e.e()
    
                //object 
                println(A.C.c)
                A.C.c()
    
                //companion object
                println(A.d)
                A.d()
            }
        }
    }
    
    内部类类型 在A类内部调用 在A类外部调用
    object C C.c(),C.c A.C.c,A.C.c()
    companion object D 可以直接使用 d,d() A.d,A.d()
    class B 实例化B对象val b = B(); b.b() ; b.b 实例化B对象val b = A.B(); b.b() ; b.b
    inner class E 实例化E对象val e = E(); e.e() ; e.e 通过外部类的实例a来实例化E对象val e = a.E(); e.e() ; e.e

    为什么这样?反编译看看源码就知道了

    A.decompiled.java

    import kotlin.Metadata;
    import kotlin.jvm.internal.DefaultConstructorMarker;
    import kotlin.jvm.internal.Intrinsics;
    import org.jetbrains.annotations.NotNull;
    
    @Metadata(
       mv = {1, 1, 15},
       bv = {1, 0, 3},
       k = 1,
       d1 = {"\u0000$\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0005\n\u0002\u0010\b\n\u0002\b\u0006\n\u0002\u0010\u0002\n\u0002\b\u0005\u0018\u0000 \u00142\u00020\u0001:\u0004\u0012\u0013\u0014\u0015B\u0005¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0011R\u0011\u0010\u0003\u001a\u00020\u00048F¢\u0006\u0006\u001a\u0004\b\u0005\u0010\u0006R\u0014\u0010\u0007\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\b\u0010\u0006R\u0014\u0010\t\u001a\u00020\nX\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u000b\u0010\fR\u001a\u0010\r\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u000e\u0010\u0006\"\u0004\b\u000f\u0010\u0010¨\u0006\u0016"},
       d2 = {"LA;", "", "()V", "a", "", "getA", "()Ljava/lang/String;", "a1", "getA1", "age", "", "getAge", "()I", "sex", "getSex", "setSex", "(Ljava/lang/String;)V", "", "B", "C", "D", "E", "baselib"}
    )
    public final class A {
       @NotNull
       private String sex = "男";
       private final int age = 11;
       @NotNull
       private final String a1 = "nan";
       @NotNull
       private static final String d = "d";
       public static final A.D D = new A.D((DefaultConstructorMarker)null);
    
       @NotNull
       public final String getSex() {
          return this.sex;
       }
    
       public final void setSex(@NotNull String var1) {
          Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
          this.sex = var1;
       }
    
       public final int getAge() {
          return this.age;
       }
    
       @NotNull
       public final String getA1() {
          return this.a1;
       }
    
       @NotNull
       public final String getA() {
          String var1 = this.sex;
          String var10000;
          switch(var1.hashCode()) {
          case 30007:
             if (var1.equals("男")) {
                var10000 = "man";
                break;
             }
          default:
             var10000 = "women";
          }
    
          return var10000;
       }
    
       public final void a() {
          A.B b = new A.B();
          b.b();
          b.getB();
          A.C.INSTANCE.c();
          D.d();
          String var10000 = d;
       }
    
       @Metadata(
          mv = {1, 1, 15},
          bv = {1, 0, 3},
          k = 1,
          d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0007R\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\b"},
          d2 = {"LA$B;", "", "()V", "b", "", "getB", "()Ljava/lang/String;", "", "baselib"}
       )
       public static final class B {
          @NotNull
          private final String b = "b";
    
          @NotNull
          public final String getB() {
             return this.b;
          }
    
          public final void b() {
             String var1 = "b() is invoked";
             boolean var2 = false;
             System.out.println(var1);
          }
       }
    
       @Metadata(
          mv = {1, 1, 15},
          bv = {1, 0, 3},
          k = 1,
          d1 = {"\u0000\u0016\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\u0010\u0002\n\u0000\bÆ\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0005R\u000e\u0010\u0003\u001a\u00020\u0004X\u0086T¢\u0006\u0002\n\u0000¨\u0006\u0006"},
          d2 = {"LA$C;", "", "()V", "c", "", "", "baselib"}
       )
       public static final class C {
          @NotNull
          public static final String c = "c";
          public static final A.C INSTANCE;
    
          public final void c() {
             String var1 = "c() is invoked";
             boolean var2 = false;
             System.out.println(var1);
          }
    
          private C() {
          }
    
          static {
             A.C var0 = new A.C();
             INSTANCE = var0;
          }
       }
    
       @Metadata(
          mv = {1, 1, 15},
          bv = {1, 0, 3},
          k = 1,
          d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\b\u0086\u0004\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0007R\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\b"},
          d2 = {"LA$E;", "", "(LA;)V", "e", "", "getE", "()Ljava/lang/String;", "", "baselib"}
       )
       public final class E {
          @NotNull
          private final String e = "e";
    
          @NotNull
          public final String getE() {
             return this.e;
          }
    
          public final void e() {
             String var1 = "e() is invoked";
             boolean var2 = false;
             System.out.println(var1);
          }
       }
    
       @Metadata(
          mv = {1, 1, 15},
          bv = {1, 0, 3},
          k = 1,
          d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0007R\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\b"},
          d2 = {"LA$D;", "", "()V", "d", "", "getD", "()Ljava/lang/String;", "", "baselib"}
       )
       public static final class D {
          @NotNull
          public final String getD() {
             return A.d;
          }
    
          public final void d() {
             String var1 = "d() is invoked";
             boolean var2 = false;
             System.out.println(var1);
          }
    
          private D() {
          }
    
          // $FF: synthetic method
          public D(DefaultConstructorMarker $constructor_marker) {
             this();
          }
       }
    }
    
    

    通过查看decompile A.kt文件之后得到的A.decompiled.java源文件
    可以得到以下几个重要信息

    • kotlin中只要不是被inner修饰的内部类,都是静态的!所以class B,object C,companion object D都是静态内部类
    • inner class E是非静态内部类,所以它会持有A的引用
    • object Ccompanion object D的构造函数都是private
    • 无论是object还是companion object中的变量都是静态常量

    梳理下

    内部类类型 是否可以定义多个 是否是单例 是否是静态内部类
    class
    inner class
    object
    companion object

    相关文章

      网友评论

        本文标题:kotlin之object,companion object,内

        本文链接:https://www.haomeiwen.com/subject/sxohictx.html