- 写在本文之前:
本文中会用到kotlin转java代码,所以这里附上使用intellij IDEA将kotlin转成java的方法:在idea中选中要查看的文件,在菜单栏中点击tools,找到kotlin,点击kotlin找到show kotlin bytecode,点击后会在窗口右边显示字节码,在字节码窗口的左上角有一个decompile,点击decompile就可以反编译成java代码
kotlin的面向对象在java的基础上做了很大的优化
访问器
在面向对象中,很多场景我们会对属性做一些限制,比如对某个属性只允许访问,不准修改,还有在对一些属性进行赋值时会进行一些校验1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23fun main(arg: Array<String>) {
var h = Human()
println(h.name)
println(h.age)
// h.name = "李四"
h.age = 20
println(h.name)
println(h.age)
}
class Human(){
var name:String = "张三"
private set
var age: Int = 18
set(value) {
if (value < 200) {
// this.age = value
field = value
}
}
}比如在这个例子中,我们要求不允许对象对name字段进行修改,那么只需要在属性下一行紧跟着使用private set,就可以将禁止对该属性进行修改,对age字段我们允许对象进行修改,但是要求年龄不允许超过200岁,所以重写在age字段后面重写set方法,就可以在赋值的时候进行一些预校验,这里需要强调的时候在set方法内,不要使用this来赋值,否则会栈溢出
通过kotlin字节码反编译成java代码,我们可以发现,在kotlin中定义的属性,会在转化成java时默认加上private权限,同时定义get和set方法,我们使用private修饰set后反编译成 Java,可以知道这相当于给set方法加了一个private属性,具体请看下面反编译生成java代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63// TestKt.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class TestKt {
public static final void main( String[] arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
Human h = new Human();
String var2 = h.getName();
System.out.println(var2);
int var3 = h.getAge();
System.out.println(var3);
h.setAge(20);
var2 = h.getName();
System.out.println(var2);
var3 = h.getAge();
System.out.println(var3);
}
}
// Human.java
import kotlin.Metadata;
import org.jetbrains.annotations.NotNull;
public final class Human {
private String name = "张三";
private int age = 18;
public final String getName() {
return this.name;
}
private final void setName(String var1) {
this.name = var1;
}
public final int getAge() {
return this.age;
}
public final void setAge(int value) {
if (value < 200) {
this.age = value;
}
}
}init方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14fun main(arg: Array<String>) {
var h = Human("李四", 23)
println(h.name)
println(h.age)
}
class Human(name: String, age: Int){
var name: String = ""
var age: Int = 0
init {
this.name = name
this.age = age
}
}init定义的是构造方法,这里面的逻辑最终会编译到java的构造函数中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65// TestKt.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class TestKt {
public static final void main( String[] arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
Human h = new Human("李四", 23);
String var2 = h.getName();
System.out.println(var2);
int var3 = h.getAge();
System.out.println(var3);
}
}
// Human.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class Human {
private String name;
private int age;
public final String getName() {
return this.name;
}
public final void setName( String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public Human( String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = "";
this.name = name;
this.age = age;
}
}使用var和val的方式定义构造方法
1
2
3
4
5
6
7
8
9
10
11
12fun main(arg: Array<String>) {
var h = Human("李四", 23)
println(h.name)
println(h.age)
// h.name = "ss"
h.age = 24
println(h.age)
}
class Human(val name: String, var age: Int){
}这段代码中定义类只用了一行代码,但它和上面的代码有同样的效果,即name不可修改,age可修改
只不过通过查看反编译后的java代码可以发现,这和private set还是有区别的,privata是将set方法设置为私有,而val定义的方式不会生成set方法,因为属性是私有的,所有同样可以起到不允许修改的作用次构造方法(构造方法重载)
在我的理解看来kotlin的次构造方法就相当于java的构造方法重载,kotlin次构造函数使用方法如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20fun main(arg: Array<String>) {
var h = Human("李四", 23)
println(h.name)
println(h.age)
println(h.phone)
// h.name = "ss"
h.age = 24
println(h.age)
var h1 = Human("王五", 40, "13788888888")
println(h1.name)
println(h1.age)
println(h1.phone)
}
class Human(val name: String, var age: Int){
var phone: String = ""
constructor(name:String,age:Int,phone:String):this(name, age){
this.phone = phone
}
}constructor就是定义次构造函数的关键词
查看对应的java代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91// TestKt.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class TestKt {
public static final void main( String[] arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
Human h = new Human("李四", 23);
String var2 = h.getName();
System.out.println(var2);
int var4 = h.getAge();
System.out.println(var4);
var2 = h.getPhone();
System.out.println(var2);
h.setAge(24);
var4 = h.getAge();
System.out.println(var4);
Human h1 = new Human("王五", 40, "13788888888");
String var3 = h1.getName();
System.out.println(var3);
int var6 = h1.getAge();
System.out.println(var6);
var3 = h1.getPhone();
System.out.println(var3);
}
}
// Human.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class Human {
private String phone;
private final String name;
private int age;
public final String getPhone() {
return this.phone;
}
public final void setPhone( String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.phone = var1;
}
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public Human( String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.age = age;
this.phone = "";
}
public Human( String name, int age, String phone) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(phone, "phone");
this(name, age);
this.phone = phone;
}
}从Java代码最后的两个构造方法可以看出,constructor其实就是定义了构造函数的重载
init 和constructor的执行顺序
init先于constructor执行