1.关键字:
constructor
关键字可以省略,但是如果构造函数有注解或可见性修饰符,则关键字不可省,如设置构造函数为私有
class Person private constructor(){
lateinit var name: String
var age: Int = 0
var parent: Person? = null
constructor(name: String, age: Int, child: Person):this(){
child.parent = this
this.name = name
this.age =age
}
constructor(name: String, age: Int):this() {
this.name = name
this.age =age
}
}
如果不存在次构造函数,默认存在一个开发的主构造函数,添加 private
修饰为私有构造函数
2.直接在跟在类名后面的是主构造函数,主构造函数constructor
可以省略
3.主构造函数和次构造函数可以共存,但是如果存在主构造方法,那么次构造函数需要直接或者间接的委托主构造函数
class Person(name:String){
var name: String = name
var age: Int = 0
var parent: Person? = null
constructor(name: String, age: Int, child: Person) :this(name,age){
child.parent = this
this.name = name
this.age =age
}
constructor(name: String, age: Int):this(name) {
this.name = name
this.age =age
}
}
4.如果不存在主构造函数,多个次构造函数可以共存,且不用委托
class Person{
var name: String
var age: Int
var parent: Person? = null
constructor(name: String, age: Int, child: Person){
child.parent = this
this.name = name
this.age =age
}
constructor(name: String, age: Int) {
this.name = name
this.age =age
}
}
5.主构造函数中不能代码,但是Kotlin提供一个init
初始代码块
//init代码块
class Person constructor(){
lateinit var name: String
var age: Int = 0
var parent: Person? = null
init {
println("I am init")
println("name = $name,age=$age,parent = $parent")
}
constructor(name: String, age: Int, child: Person):this(){
child.parent = this
this.name = name
this.age =age
}
constructor(name: String, age: Int):this() {
this.name = name
this.age =age
}
}
注意
(1) 如果存在主构造函数,类的属性必须存在初始化值或者用延迟加载关键字lateinit
。但是 lateinit
只能修饰非Kotlin基础类型,如String等
(2)init
初始块在优先执行(次构造函数之前执行),如果执行过程中延迟加载的变量没有赋值,会报异常
Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property name has not been initialized
(3) lateinit
只能用于类体的var属性,不能用于构造函数中
(4) lateinit
不能用于拥有定制getter
和setter
方法的属性
6.主构造函数的多种表示法
//主构造函数 直接定义属性
class Person(var name: String, var age: Int) {
}
//主构造函数 只传递参数 函数体内赋值
class Person1(name: String, age: Int) {
var name = name
val age = age
}
7.构造函数属性可以函数类型
////主构造函数 属性为函数类型
class Person( num1: Int, num2: Int,operator:(Int,Int)->Int) {
lateinit var name :String
init {
println("operator = ${operator(num1,num2)}")
}
constructor(num1: Int, num2: Int):this(num1,num2,operator = {x,y->x+y}){
}
}
8.属性
(1) var 默认有一般的公开getter和setter属性,可以直接通过.进行赋值和取值;
(2) val 默认有一般的公开getter,可以直接通过.进行取值,没有setter方法;
(3)属性定制;
- 订制为私有 private set , 没有 private get,如果想属性不被公开,直接在属性前面添加private
- 在get 和 get中不可以使用属性,否则会造成循环引用,Kotlin使用幕后字段field解决无限循环问题,所有需要使用字段自身的地方用field代替
- get 和set可以任意定制,定义其中一个的话,另一个则为默认
///主构造函数 属性getter 和setter
class Person(age: Int) {
//重写get和set方法
var name: String = ""
get() = "My name is" + field
set(value) {
field = value
}
var age: Int = age
set(value) {
field = value
if (value >= 18) {
isAdult = true
}
}
// 属性定制为私有
var isAdult: Boolean = false
private set
var addAge: Int = 0
get() {
return field + 1
}
set(value) {
field = value
age += value
}
constructor(age: Int, name: String) : this(age) {
this.name = name
}
override fun toString(): String {
return "name =$name,age=$age,isAdult = $isAdult,addAge = $addAge"
}
}
9.编译期常量
关键字:const
只能修饰 val
特点:
- 只能位于顶层或者object的成员,不能修饰一般类成员
- 只能修饰原始数据类型和String
- 没有自定义getter方法
- 区别val 和const val :str1 在传递的过程中是引用str1,str2在传递的过程中是传递str2的值”Hello Kotlin”
Kotlin代码
package `object`
val str1 = "Hello Kotlin"
const val str2 = "Hello Kotlin"
fun main(args: Array<String>) {
var str3 = str1
var str4 = str2
}
反编译成java代码
public final class ConstTestKt {
@NotNull
private static final String str1 = "Hello Kotlin";
@NotNull
public static final String str2 = "Hello Kotlin";
@NotNull
public static final String getStr1() {
return str1;
}
public static final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
String str3 = str1;
String str4 = "Hello Kotlin";
}
}