通过java中互相调用和编译后的字节码或反编译来分析。本质上是能够相互转换代码的。
1. 对象申明:修饰class名
object className {} 的类名申明方式。
object ObjectClass {
var a = 0
fun foo(){}
}
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(){}
}
}
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() {
}
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)
}
})
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 对象表达式-直用-函数
fun publicFoo() = object {
val x: String = "y"
fun getValue() = 6
}
private fun foo() = object {
val x: String = "y"
fun getValue() = 6
}
fun test() {
val f = foo()
val xx = f.x
f.getValue()
}
1.5 对象表达式-直用-变量
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()
}
内存泄漏研究
仔细阅读下图。是通过仔细分析字节码研究出来的,有错误之处,尽情回复拍砖。 kotlin唯一的好处是,对于没有引用外部类实例的情况下,在对象表达式上有所优化。
kotlin分为: 静态内部类,内部类,匿名内部类,lambda表达式。
第一种:java内部不用static修饰,持有外部引用,对应kotlin 添加inner标记; 第二种:java内部使用static修饰,不持有外部引用,对应直接申明class的kotlin内部类;
public class Test {
int x = 1;
class Inner{
void a() {
x = x + 1;
}
}
static class Inner{
void a() {
x = x + 1;
}
}
void foo() {
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
}
void foo() {
new Thread(() -> {
}).start();
}
class MyClass {
var aaa = "a"
inner class NestClass {
fun a(): String {
return aaa
}
}
class NestClass {
fun a(): String {
return aaa
}
}
}
|