通过java中互相调用和编译后的字节码或反编译来分析。本质上是能够相互转换代码的。

1. 对象申明:修饰class名

object className {} 的类名申明方式。

object ObjectClass {
    var a = 0
    fun foo(){}
}

//反编译得到如下
/* loaded from: ObjectClass.class */
public final class ObjectClass {
    public static final ObjectClass INSTANCE = new ObjectClass();
    private static int a;

    private ObjectClass() {
    }

    public final int getA() {
        return a;
    }

    public final void setA(int i) {
        a = i;
    }

    public final void foo() {
    }
}

因此,object class就是java中,final的class配上private构造函数,加恶汉单例INSTANCE
如果我们要在java中调用,还得通过MyCalss.INSTANCE.a()来调用。
备注:想让a()函数变成static,则通过注解@JVMStatic注解来实现,对象变量通过@JVMField

object ObjectClass {
    @JvmField
    var a = 0

    @JvmStatic
    fun foo(){}
}
//反编译成如下:
public final class ObjectClass {
    @NotNull
    public static final ObjectClass INSTANCE = new ObjectClass();
    @JvmField
    public static int a;

    private ObjectClass() {
    }

    @JvmStatic
    public static final void foo() {
    }
}

2. 伴生对象:companion object

class MyClass {
   companion object {
       val aa = 1
       fun a(){}
   }
}

//反编译为java代码如下:
public final class MyClass {
   private static final int aa = 1;
   public static final Companion Companion = new Companion((DefaultConstructorMarker)null);
    
   public static final class Companion {
      public final int getAa() {
         return MyClass.aa;
      }

      public final void a() {
      }

      private Companion() {
      }

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

在Kotlin中调用MyClass.a(), 在Java中调用 MyClass.Companion.a(); 理解第一章的object class后,再理解伴生对象事半功倍。变量是放在主类中的static变量。而函数则是伴生类(静态内部类)中的函数。同样的,觉得这种调用不爽,可以通过注解@JVMStatic或者@JVMField处理。

3. 对象表达式

3.1 基本用法
Thread(object :Runnable{
    override fun run() {
        println("hah")
    }
}).start()

Collections.sort(list, object : Comparator<String?> {
    override fun compare(o1: String?, o2: String?): Int {
        if (o1 == null) {
            return -1;
        }
        if (o2 == null) {
            return 1;
        }
        return o1.compareTo(o2)
    }
})
//lambda写法
Collections.sort(list, { o1: String, o2: String ->
        if (o1 == null) {
            return@sort -1;
        }
        if (o2 == null) {
            return@sort 1;
        }
        return@sort o1.compareTo(o2)
})

匿名内部类,也会有IDEA提示,建议改成lambda(备注2点,第一点,有的可以提示,有的不提示。第二点,与java不同,java里面箭头后面用花括号包住即可,而kotlin不能添加{})。kotlin的lambda省略写法很多,这里不做介绍,按照idea提示自行转换吧。

3.2 更强大的用法

多个继承使用,达到了超越java的匿名内部类的能力。

val superMan = object: Man("Clark"), Flyable, SuperHearing, SuperVision {
        override fun hearSubtleNoises() {
        }
        override fun seeThroughWalls() {
        }
        override fun fly() {
        }
    }
3.3 对象表达式-直用-函数
//Object a = clas.publicFoo();
    //外部只能获取到一个object。没有任何用处。
    //推荐如下加上private。
    fun publicFoo() = object {
        val x: String = "y"
        fun getValue() = 6
    }

    //私有object表达式
    private fun foo() = object {
        val x: String = "y"
        fun getValue() = 6
    }
    //测试上面的代码
    fun test() {
        val f = foo()
        val xx = f.x
        f.getValue()
    }
1.5 对象表达式-直用-变量
//无法被引用内部参数,是个any
val publicValue = object  {
    val x: String = "y"
    fun getValue() = 6
}
//可以被引用
private val privateValue = object {
    val x = "aaa"
    fun getValue() = 7
}

private fun test() {
    privateValue.x
    val v = privateValue.getValue()
}

内存泄漏研究

仔细阅读下图。是通过仔细分析字节码研究出来的,有错误之处,尽情回复拍砖。

java kotlin定义数据类型 kotlin object class_android


kotlin唯一的好处是,对于没有引用外部类实例的情况下,在对象表达式上有所优化。

kotlin分为:
静态内部类,内部类,匿名内部类,lambda表达式。

第一种:java内部不用static修饰,持有外部引用,对应kotlin 添加inner标记;
第二种:java内部使用static修饰,不持有外部引用,对应直接申明class的kotlin内部类;

public class Test {
    int x = 1;
    //《1. 内部类》:会持有外部引用。
    class Inner{
        void a() {
            x = x + 1;
        }
    }
    //《2. 静态内部类》不持有外部引用
    static class Inner{
        void a() {
            x = x + 1;
        }
    }
    
     void foo() {
        //new Runnable属于《3. 匿名内部类》
        new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();
    }
    
    void foo() {
        //《4. lambda》
        new Thread(() -> {
        
        }).start();
    }
class MyClass {
    var aaa = "a"
    //持有外部引用。
    inner class NestClass {
        fun a(): String {
            return aaa
        }
    }
    //不持有外部引用,相当于static final class
	class NestClass {
        fun a(): String {
            return aaa
        }
    }
}