只赋值一次的(只读)局部变量:
val a: Int = 1
val b = 1 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 1 // definite assignment
可变的变量
var x = 5 // `Int` type is inferred
x += 1
定义属性
在Kotlin的类中可以拥有属性。这些可以声明为可变的,使用使用val关键字var关键字或只读。
public class Address {
public var name: String = ...
public var street: String = ...
public var city: String = ...
public var state: String? = ...
public var zip: String = ...
}
使用属性,我们只是将它的name
,就好像它是在Java字段:
fun copyAddress(address: Address): Address {
val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}
完整的语法来声明一个属性
var <propertyName>: <PropertyType> [= <property_initializer>]
<getter>
<setter>
initializer,getter和setter是可选的。属性类型是可选的,如果它可以推断出从基类成员初始化或被覆盖
例如:
var allByDefault: Int? // error: explicit initializer required, default getter and setter implied
var initialized = 1 // has type Int, default getter and setter
note,类型不能推断属性为public公共API的一部分,即public和protected,因为改变初始化可能导致一个无意的公共API的变化。例如:
public val example = 1 // error: a public property must have a type specified explicitly
一个只读属性声明的全部语法不同于一个可变的一个在两个方面:它开始于val 代替var和不允许一个setter
val simple: Int? // has type Int, default getter, must be initialized in constructor
val inferredType = 1 // has type Int and a default getter
我们可以编写自定义的访问器,非常像普通函数,对内部属性声明。这里有一个定制的getter的例子:
val isEmpty: Boolean
get() = this.size == 0
一个定制的setter看起来像这样:
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
按照惯例,setter的名称参数value
,但是如果你喜欢你可以选择一个不同的名称
如果你需要改变一个访问器或注释的可见性,但是不需要改变默认的实现中,您可以定义访问器不定义它的身体:
var setterVisibility: String = "abc" // Initializer required, not a nullable type
private set // the setter is private and has the default implementation
var setterWithAnnotation: Any?
@Inject set // annotate the setter with Inject
在Kotlin类不能有领域。然而,有时有必要有一个支持字段在使用定制的访问器。为这些目的,Kotlin提供了一个自动支持字段可以使用$符号访问属性名紧随其后。
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0)
$counter = value
}
$counter
字段只能从内部访问counter
属性的类定义
编译器的访问器的机构,如果他们使用支持字段(或违约)留下的访问器实现,生成一个支持字段,否则不是
例如,在以下情况下将没有支持字段
val isEmpty: Boolean
get() = this.size == 0
如果你想做一些不符合这个“暗中支持字段”计划,您总是可以回到有支持属性:
private var _table: Map? = null
public val table: Map
get() {
if (_table == null)
_table = HashMap() // Type parameters are inferred
return _table ?: throw AssertionError("Set to null by another thread")
}
在各方面,这只是在Java一样因为访问私有属性默认getter和setter方法优化,介绍了函数调用的开销。
See Overriding Members