Kotlin对比Java 入门学习记录(陆)

Kotlin入门学习记录
2023/12/02 - 2023/12/03

Class

KT中默认关键字为Java中的public final,并且添加属性时会自动添加gettersetter方法,代码实现如下

class Player{
    var name = "LY_C"
}

在Jvm字节码中转为Java,如下

public final class Player {
   @NotNull
   private String name = "LY_C";
   @NotNull
   public final String getName() {
      return this.name;
   }
   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }
}

在修改name属性值时,默认是使用setter函数,代码使用如下

fun main() {
    var player = Player()
    player.name = "CRY"
}

在Jvm字节码中转为Java,如下

public static final void main() {
	Player player = new Player();
	player.setName("CRY");
}

field关键字

在声明属性时KT会添加field关键字,该关键字指的是某个属性,KT会封装属性给field保护属性,只暴漏给gettersetter函数,代码实现如下

class Player{
    var name = "LY_C"
        get() = field.capitalize()
        set(value) {
            field = value.trim()
        }
}

在Jvm字节码中转为Java,如下

public final class Player {
   @NotNull
   private String name = "LY_C";
   @NotNull
   public final String getName() {
      return StringsKt.capitalize(this.name);
   }
   public final void setName(@NotNull String value) {
      Intrinsics.checkNotNullParameter(value, "value");
      this.name = StringsKt.trim((CharSequence)value).toString();
   }
}

getter

在获取属性值时使用的是getter函数,代码实现如下

fun main() {
    var player = Player()
    player.name = "cry"
    println(player.name)//Cry
}

在Jvm字节码中转为Java,如下

public static final void main() {
	Player player = new Player();
	player.setName("cry");
    String var1 = player.getName();
    System.out.println(var1);
}

计算属性

计算属性是使用gettersetter覆盖定义一个属性,可以不使用field,代码实现如下

class Player{
    val age
        get() = (0..100).shuffled().first()
}
fun main() {
    var player = Player()
    println(player.age)
}

防静态竞争

如果一个属性是var又是可空类型的,调用属性时需要使用空安全操作符

主构造体

KT中的主构造体直接写道类名之后,类似于Java中的record类,不加varval可以声明临时变量,临时变量名一般命名为_开头,代码实现如下

class Player(_name:String,_age:Int){
    var name = _name
        get() = field.capitalize()
    var age = _age
}
fun main() {
    var player = Player("cRY",21)
    println(player.name)//CRY
}

Javarecord代码实现如下

public record Player(String name,int age) {
    @Override
    public String name() {
        return _name.toUpperCase();
    }
}
class _Main{
    public static void main(String[] args) {
        Player player = new Player("cRY", 21);
        System.out.println(player.name());//CRY
    }
}

次构造函数

在类中使用constructor关键字,次构造函数要么直接调用主构造函数(传入它需要的值参),要么通过调用另一个次构造函数间接调用主构造函数,this 就是在调用当前类的主构造函数,代码实现如下

class Player(_sex: String,_name:String, _age:Int){
    constructor(_sex:String):this(_sex, _name = "LY_C", _age = 21 )
    var sex = _sex
    var name = _name
        get() = field.capitalize()
    var age = _age
}
fun main() {
    var player = Player("female","cRY",21)
    println(player.sex + player.age + player.name)//female21CRY
    var player1 = Player("male")
    println(player1.sex + player1.age + player1.name)//male21LY_C
}

可以定义多个次构造函数,也可以在次构造函数中写初始化代码逻辑,代码实现如下

class Player(_sex: String,_name:String, _age:Int){
    constructor(_sex:String):this(_sex, _name = "LY_C", _age = 21 )
    constructor(_sex: String,_age: Int):this(_sex, _name = "LY_C",_age){
        this.age += 1
    }
    var sex = _sex
    var name = _name
        get() = field.capitalize()
    var age = _age
}
fun main() {
    var player1 = Player("male")
    println(player1.sex + player1.age + player1.name)//male21LY_C
    var player2 = Player("male",20)
    println(player2.sex + player2.age + player2.name)//male21LY_C
}

初始化块

在类中使用init关键字,完成初始化块的编写,一般结合require实现对数据的检查,代码实现如下
注意
require判断条件是反逻辑,如果为false会抛出IllegalArgumentException异常
与Java中的静态代码块的区别是Java的静态代码块在类加载时执行,
而KT的init在构造函数中执行

class Player(_sex: String,_name:String, _age:Int){
    init {
        require(_age > 0){"年龄必须大于0"}
        require(_name.isNotBlank(),{"姓名不能为空串"})
    }
    ...
}

Java中的静态代码块实现如下

public class Player{
    static {
        System.out.println("静态代码块");
    }
    ...
}

初始化顺序

KT:主构造体声明的属性 -> 类级别属性赋值 -> init初始化代码块 -> 次构造体和函数调用

//1.age
class KT_Student(_name:String, var age:Int) {
//2.name,scorce,hobby
    var name = _name
    var scorce = 10
    private val hobby = "music"
    val subject:String
//3.subject
    init {
        subject = "Kotlin编程权威指南"
        println("initing")
    }
//4.name,age,scorce
    constructor(_name:String):this(_name,21){
        scorce = 90
    }
}
fun main() {
    KT_Student("LY_C")
}

Java:静态变量和静态代码块 -> 类级变量和初始化块 -> 构造器
注意
静态变量和静态初始化块,在类加载时初始化,只初始化一次

public class Java_Student {
	//1.name
	static String name = "LY_C";
    //1.static{}
    static {
        
    }
    //2.sex,age,{}
    String sex = "male";
    int age = 21;
    {

    }
    //3.name,sex,age
    public Java_Student(String name, String sex, int age) {
        Java_Student.name = name;
        this.sex = sex;
        this.age = age;
    }
}

惰性初始化

使用lateinit完成延迟初始化,即告诉编译器在赋值时初始化,可以使用反射isLateinit判断是否初始化完成
注意
lateinit只能和var一块使用,并且必须指定类型,代码实现如下

class KT_Student(var name:String, var age:Int) {
	lateinit var subject:String
    init {
        subject = "Kotlin编程权威指南"
    }
	override fun toString() = "${name} ${age} ${subject}" +
	 	if (::subject.isLateinit) "初始化完成" else "未初始化"
}
fun main() {
    var student = KT_Student("LY_C", 21)
    println(student)//LY_C 21 Kotlin编程权威指南初始化完成
}

延迟初始化

使用by lazy关键字完成延迟初始化,当首次使用才进行初始化,代码实现如下

class KT_Student(var name:String, var age:Int) {
    val id by lazy { loadId() }
    fun loadId():Int{
        print("初始化")
        return 1
    }
}
fun main() {
    var student = KT_Student("LY_C", 21)
    print(student.id)//初始化1
}

初始化陷阱

本质上是代码顺序的问题

  1. 在使用初始化代码块时,一定要保证块内的变量已经完成初始化,以下为错误演示
class KT_Init{
    init {
        val bloodBonus = blood.times(3)
    }
    var blood = 100
}
  1. 编译器通过但会出现空指针异常,以下为错误演示
class KT_Init{
    val name:String
    private fun firstLetter() = name[0]
    init {
        println(firstLetter())//没有初始化就被调用
        name = "LY_C"
    }
}
  1. 在用InitName函数初始化 initName 时,name 属性应该已完成初始化,但实际并非如此
class KT_Init(_name:String){
    val initName = InitName()
    val name = _name
    private fun InitName() = name;
}
fun main() {
    var ktInit = KT_Init("LY_C")
}
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuKey_C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值