只读变量
只读变量
可以理解为java中的常量用final关键机修饰的变量。kotlin中只读变量用val关键字修饰:
val a = 1//通过值可以推导出a的类型可以省略变量类型Int
val b: Int = 2//声明的时候就给赋值
class Test(){
init {
val c: Int // 在声明时没有赋值,变量类型Int不可省去,
c = 3//只能初始化一次此后不会再改变
}
}
可变变量
可以理解为java中的普通变量,kotlin中用var关键字声明可变变量,var与val声明的变量最大的却别就是:var声明的变量可以随时给它赋值
var a = 1
a = 2
a = 3
成员变量
和java一样,通过对象点属性名来调用(obj().property)
class Test {
var name= "guojingbu"
}
fun main() {
print(Test().name)
}
静态变量
kotlin中的静态变量需要声明在companion object {}
闭包中,纯kotlin中调用时可以用类名.变量名
。
在纯kotlin代码中可以直接这样使用:
class Test {
companion object {
val name: String = "guojingbu"
//const只能用在顶级属性中
// const val 相当于java的 public static final修饰的常量
const val Url = "http://baidu.com"
}
}
fun main() {
println(Test.Url)
println(Test.name)
}
java代码中调用kotlin的静态变量时可以这样使用
//kotlin代码:
class Constant {
companion object {
// 接口根地址
const val BASE_URL = "http://baidu.com"
val name="guojingbu"
}
//java代码
public class JavaCallKotlin {
public static void main(String[] args) {
//kotlin中被const修饰的常量的访问方式
String url = Constant .BASE_URL ;
//kotlin代码中未被const修饰的只读变量的访问方式
String name=Constant .Companion.getName();
}
}
顶级变量
顶级变量是声明在类外部的变量其他类文件中需要访问时需要用包名.变量名
的方式才能访问到(如下列代码:)
类文件GrammarBasic.kt
package com.gjb.grammar_lib
var a = 10;
类文件TestTopVar.kt
fun main() {
print(com.gjb.grammar_lib.a)
}
变量的getter和setter方法
首先我们随便创建一个类User并给它创建一些不同可见性成员属性
package com.gjb.grammar_lib
var rootVar:String=""
class User{
var name:String=""
val age:Int=20
private var sex:Int=0
internal var birthday:String=""
protected var address:String=""
}
我们通过以下步骤把kotlin类反编译成java类来看看它对应的java类是什么样子的
public final class User {
@NotNull
private String name = "";
private final int age = 20;
private int sex;
@NotNull
private String birthday = "";
@NotNull
private String address = "";
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final int getAge() {
return this.age;
}
@NotNull
public final String getBirthday$grammar_lib() {
return this.birthday;
}
public final void setBirthday$grammar_lib(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.birthday = var1;
}
@NotNull
protected final String getAddress() {
return this.address;
}
protected final void setAddress(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.address = var1;
}
}
// UserKt.java
package com.gjb.grammar_lib;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class UserKt {
@NotNull
private static String rootVar = "";
@NotNull
public static final String getRootVar() {
return rootVar;
}
public static final void setRootVar(@NotNull String var0) {
Intrinsics.checkParameterIsNotNull(var0, "<set-?>");
rootVar = var0;
}
}
从上面的kotlin代码和java代码对比可知,protected和public会生成对应的setter和getter方法,internal也生成了特殊的对应方法。
所以对于protected和public的成员变量,我们不能自己创建对应的getter和setter方法。对于根变量rootvar会生成一个对应的内部类UserKt里面会创建根变量的setter和getter方法,如
var name:String?
fun setName(name:String){}
如果我们自行的去创建对应属性的setter和getter方法编译器会报如下错误:
Platform declaration clash: The following declarations have the same JVM signature (setName(Ljava/lang/String;)V)
getter和setter方法的可见性
- 对于getter方法
getter的可见性和变量的可见性相同,无需重复添加修饰符,如果你非要指定它的可见性必须和变量的可见性一致,否则编译器会报如下错误:
var name:String=""
public get//报错: Getter visibility must be the same as property visibility
- 对于setter
setter的可见性必须小于等于变量自身的可见性,否则报错,如:
internal var birthday:String=""
// private set
// internal set
protected set //error:Setter visibility must be the same or less permissive than property visibility
我们也可以自定义setter和getter方法
- 语法
<var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
其初始器(initializer)、getter 和 setter 都是可选的。属性类型如果可以从初始器 中推断出来,也可以省略。
class User{
var name:String="guojingbu"
set(value){
field = value
}
get() {
return field+" ai zhangwei"
}
}
fun main() {
val user = User()
println(user.name)
user.name="郭雨萱"
println(user.name)
}
打印结果:
guojingbu ai zhangwei
郭雨萱 ai zhangwei