先回顾下一个很经典的java初始化题
class A {
static {
System.out.println("static A");
}
{
System.out.println("init A");
}
public A() {
System.out.println("constructor A");
}
}
class B extends A {
static {
System.out.println("static B");
}
{
System.out.println("init B");
}
public B() {
System.out.println("constructor B");
}
public static void main(String[] args) {
B b = new B();
}
}
运行后打印结果为
static A
static B
init A
constructor A
init B
constructor B
java中清晰区分了静态语句块、初始化语句块、构造方法三个初始化,复习结束。
将A和B两个类转成kotlin代码
internal open class A {
companion object {
init {
println("static A")
}
}
init {
println("init A")
}
init {
println("constructor A")
}
}
internal class B : A() {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val b = B()
}
init {
println("static B")
}
}
init {
println("init B")
}
init {
println("constructor B")
}
}
将B转成java
public final class B extends A {
@NotNull
public static final B.Companion Companion = new B.Companion((DefaultConstructorMarker)null);
public B() {
String var1 = "init B";
System.out.println(var1);
var1 = "constructor B";
System.out.println(var1);
}
static {
String var0 = "static B";
System.out.println(var0);
}
@JvmStatic
public static final void main(@NotNull String[] args) {
Companion.main(args);
}
public static final class Companion {
@JvmStatic
public final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
new B();
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
可以看到kotlin会把java中的初始化语句块给移到构造方法中!
这样在开发中会出现一些问题,比如:
class C {
val beforeValueSet = Int.also {
System.out.println("before value set value=${value}")
}
val value = 1
val afterValueSet = Int.also {
System.out.println("after value set value=${value}")
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
val c = C()
}
}
}
打印结果是:
before value set value=0
after value set value=1
为什么呢?value明明是不可变的,明明变量声明时就直接赋值为1了呀!
private final int value;
public C() {
System.out.println("before value set value=" + this.value);
this.value = 1;
System.out.println("after value set value=" + this.value);
}
如果value不是基本类型,而是对象
class D {
val beforeValueSet = Int.also {
System.out.println("before value set value=${value}")
}
val value = "value"
val afterValueSet = Int.also {
System.out.println("after value set value=${value}")
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
val d = D()
}
}
}
那不可空的变量里竟然读出了可空的值!
before value set value=null
after value set value=value
原理跟上面的一样,直接看java代码
@NotNull
private final String value;
public D() {
System.out.println("before value set value=" + this.value);
this.value = "value";
System.out.println("after value set value=" + this.value);
}