Kotlin-Learning 属性和字段

声明

var 代表可变。
val 代表只读。

后面加冒号可以指定类型。必须初始化,不像 java 有默认值。

var a:String = "a"
复制代码

可以用?表示可以为 null

var a:String? = null
复制代码

Getter 和 Setter

声明属性的完整语法。包括类型指定,初始化值,getter,setter。默认会自动实现 getter setter。

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
复制代码

可以不直接初始化,但必须在构造中初始化。

class PropertiesAndFields {
    private val a: String?
    private val simple: Int?

    init {
        a = null
        simple = 3
    }
}
复制代码

get() 和 set() 的意思很简单,当读取 a 的值时会调用 get(), 给 a 写值时,会调用 set()

var a: String?
    get() = "wenchieh"
    set(value) = println(value)
    
fun main(a: Array<String>) {
    // 每次读值都会走get(), 写值后读的还是 get 的值
    println(a)
    propertiesAndFields.a = "qweqwe"
    println(a)
}

输出:
wenchieh
qweqwe
wenchieh
复制代码

val 只有 get(),因为它是只读的。

1.1 之后可以根据 get() 类型自动推测。省略类型,不能初始化。

val isEmpty
    get() = this.size == 0 // 推测为 Boolean 类型
复制代码

var 必须定义 get() set()。set 中不能引用 field。才不必初始化。

var isEmpty2
    get() = a.size == 0
    set(value) {
       println("asdad")
    }
复制代码

给默认的 set get 添加注解和可见性修饰符:

var b = 2
    private set
    @InitConciseSyntax.Inject get
复制代码

Backing Fields

Java中的属性和字段有什么区别

Kotlin 中没有字段,只有属性。默认都有 getter getter。

在 getter setter 中,Kotlin 提供一个 field 关键字的字段。

var backingField: Int = 2 // field 被初始化为2
    get() {
        if (field >= 0) {
            return field
        }
        return -1
    }
    set(value) {
        if (value >= 0)
            field = value
    }
复制代码

如果使用了 field 就会生成。没使用就没有这个字段。

为什么 var 属性自定义 getter 还需要初始化?

val greeting: String
    get() = "hello"
复制代码

val 只有 getter, get() 没有用到 field 字段,不初始化是可以的。var 有 seteer 和 getter,set() 和 get() 都没有用到 field 时才可以不用初始化。

// get 用到了 field 必须初始化,field 才有值
val greeting: String 
    get() = field
复制代码
var greeting: String
    get() = "hello"
    set(value) { println(value)}
复制代码

Backing Properties

如果不适合使用 Backing Field,可以使用 Backing Properties。和 Java 类似

// Backing Properties
private var aTable: Map<String, Int>? = null
val table: Map<String, Int>
    get() {
        if (aTable == null) {
            aTable = HashMap()
        }
        return aTable ?: throw AssertionError("Set to null by another thread")
    }
复制代码

编译时常量

在编译时已知其值的属性可以使用 const 修饰符标记为编译时常量。const 只能修饰 val

类似于 Java 的 static final.

编译时常量需满足:

  1. 在top-level声明的 或者 是一个object的成员(Top-level or member of an object)
  2. 以String或基本类型进行初始化
  3. 没有自定义getter

可以在注解中使用这些属性。

const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprected(SUBSYSTEM_DEPRECATED) fun foo() { ... }
复制代码

延迟初始化

使用 lateinit 修饰符,延迟加载。

需满足条件:

  1. 只能修饰 var
  2. 不能用于主构造函数中
  3. 不能为 null
  4. 类型不能为基本类型
  5. 属性不能有自定义的 getter setter

如果 lateinit 在初始化之前被访问了,会抛出一个特定的未初始化错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值