Kotlin学习(三):表达式

12 篇文章 0 订阅

系列文章路引 👀 https://blog.csdn.net/weixin_44235109/article/details/119680974

一、常量与变量(var、val、const的使用与区别)

1.var、val、const的使用与区别

var 称为可读写变量 如下和java对比所示:

//java
int a = 2;
a = 3;
//kotlin
var a = 2
a = 3

val 称为只读变量(不能称为常量,因为是在运行时才确定的值,也称作运行时常量)。如下和java对比所示:

//java
final int a = 2;
//kotlin
val a  = 2

const val 和 java静态常量类似,称作编译时常量(在编译期间即可确定的值)。
只能定义在全局范围
只能修饰基本类型
必须立即用字面量初始化

//java
static final int b = 3;
//kotlin
const val b = 3

2.编译期和运行时常量

const val b = 3 编译器即可确定常量的值 , 并用值替换调用处
val c : Int 运行时才能确定的值 , 调用处通过引用获取值
如下:

//const val b = 3  字面量必须立即初始化
const val b = 3
//val c : Int  只有在运行时  才确定 c的值  所以也称作 运行时常量
val c: Int
if (b == 2) {
    c = 2
} else {
    c = 3
}

二、分支表达式

1. if…else

kotlin里面if…else可以当作表达式使用,例如:

c = if(a==3) 4 else 5

2.when表达式 类似于 java的switch

与java switch对比如下:

//java
switch(a){
	case 0 : c = 5; break;
	case 1 : c = 4; break;
	default : c = 20 ;
}
//kotlin
when(a){
	0 -> c = 5
	1 -> c = 4
	else -> c = 20
}

when 多个值相同 可用,间隔 如下所示:

when(a){
	0 , 2 -> c = 5
	1 -> c = 4
	else -> c = 20
}
//也可写为
c = when(a){
	0 , 2 -> 5
	1 -> 4
	else -> 20
}

3.try…catch

try…catch 也是表达式,可直接将变量提取使用

//java
try{
	c = a/b;
}catch(Exception e){
	e.printStactTrace();
	c = 0;
}
//kotlin
c = try{
	a/b
}catch(e:Exception){
	e.printStactTrace()
	0
}

三、kotlin运算符重载与中辍表达式

1.kotlin运算符重载

运算符operator,kotlin支持运算符重载,但是运算符的范围仅限官方指定的符号:官网路径
用于重载运算符的所有函数都必须使用operator关键字标记。如下简单的demo所示:

// 一个简单的数据类
data class Foo(val x: Int, val y: Int) {
    operator fun plus(other: Foo) : Foo = Foo(x + other.x, y + other.y)
}

fun main(args: Array<String>) {
    // 使用的时候
    val f1 = Foo(10, 20)
    val f2 = Foo(30, 40)
    // 直接用+运算符代替plus函数,事实上会调用plus函数
    println(f1 + f2) // 打印内容为Foo(x=40, y=60)
}

也可以使用扩展函数对运算符进行重载,如下所示:

//    自定义复数运算符  重载运算符
/**
 * @param real 实部
 * @param image 虚部
 */
class Complex(var real: Double, var image: Double) {
    override fun toString(): String {
        return "real:$real image:${image}i"
    }
}
//  使用扩展方法  进行运算符重载
operator fun Complex.plus(other: Complex): Complex {
    return Complex(this.real + other.real, this.image + other.image)
}

operator fun Complex.plus(other: Double): Complex {
    return Complex(this.real + other, this.image)
}

operator fun Complex.plus(other: Int): Complex {
    return Complex(this.real + other, this.image)
}

operator fun Complex.minus(other: Complex): Complex {
    return Complex(this.real - other.real, this.image - other.image)
}

fun main(){
	//    运行  自定义复数例子
    val complex1 = Complex(3.0, 2.0)
    val complex2 = Complex(2.0, 3.0)
    //使用
    println((complex1 + complex2).toString())
    println((complex1 + 1).toString())
    println((complex1 + 1.2).toString())
    println((complex1 - complex2).toString())
}

除了上述的加减之外,kotlin还支持其他类型的运算符重载,具体可上,官网查看。
Demo:为String实现四则运算

//    为string实现四则运算

//    minus 减
operator fun String.minus(right: Any?): String {
    val str = right?.toString() ?: ""
    return this.replaceFirst(str, "")
}

//    times
operator fun String.times(right: Int): String {
    return (1..right).joinToString("") { this }
}

//    div  除
operator fun String.div(right: Any?): Int {
    val str = right?.toString() ?: ""
//   windowed 返回给定大小的窗口的快照列表,这些快照沿着给定步骤的字符序列滑动,其中每个快照都是一个字符串。 count  返回为true的个数
    return windowed(str.length, 1) {
        it == str
    }.count { true }
}

fun main() {
    val str = "hello world world"
//    minus
    println(str - "hello")
//    times
    println("*" * 20)
//    div
    println(str / "l")
}

2.kotlin中辍表达式 infix

中辍表达式使用infix标记
那什么是中辍表达式呢?
在第一章学习的时候,我们知道Pair是一个对象 包含两个值,frist以及second 。源码如下所示:

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable {

    /**
     * Returns string representation of the [Pair] including its [first] and [second] values.
     */
    public override fun toString(): String = "($first, $second)"
}

如何快速生成Pair呢? 如下所示

val pair1: Pair<Int, Int> = 2 to 3

这个to就是一个中辍表达式,定义源码如下:

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

仿照上方源码,我们自定义一个中辍表达式,如下:

//    定义中辍表达式
infix fun String.rotate(count: Int): String {
    val index = count % this.length
    return this.substring(index) + this.substring(0, index)
}

fun main(){
//    使用自定义的中辍表达式
    val s = "helloworld" rotate 5
    println(s)
}

//运行结果为
worldhello

四、Lambda表达式

1.kotlin匿名函数

kotlin普通函数以及kotlin匿名函数对比

//一个普通函数
fun func(){
	println("hello")
}
//一个匿名函数
fun(){
	println("hello")
}
//匿名函数的引用
val func = fun(){
	println("hello")
}

//对引用的匿名函数调用
func()

2.匿名函数的类型

kotlin匿名函数的类型与普通函数一致

val func : () -> Unit = fun(){
	println("hello")
}

3.Lambda表达式的定义,java与kotlin对比

示例如下所示(其中java的实例,指的是从java8开始):

//java
Runnable lambda = () -> {
	System.out.println("hello");
}
//kotlin
val lambda = {
	println("hello")
}

lambda表达式的类型

//类型1  入参Int  无返回
val f1 : (Int) -> Unit = {
	p:Int ->
	println(p)
}

//类型2  入参Int  返回String
val f2 : (Int) -> String= {
	p:Int ->
	println(p)
	"hello"
}

//类型3  入参Int,String  返回String
val f3 : (Int,String) -> String= {
	p:Int,s:String ->
	println("$p$s")
	"hello"
}

lambda表达式省略参数的写法,如果只有一个参数,可使用it代替

val f : Function1<Int,Unit> = {
	println(it)
}

总结

以上便是本节,kotlin表达式相关的内容了。
下面可以写demo练习一下,如下:为person实现equals和hashcode方法

class Person(var age: Int, var name: String) {
    //  set比较:  hashcode  相等  不一定相等  但是hashcode不等  则比较一定不等
    override fun hashCode(): Int {
//    拿age和name作为固定值返回   相同的字符串调用hashCode()方法,得到的值是一样的,与内存地址、进程、机器无关。
        return age + name.hashCode()
    }

    override fun equals(other: Any?): Boolean {
//        用as  做安全的类型转换  如果转换不对返回null  则使用?:处理
        val person = other as? Person ?: return false
        return this.age == person.age && this.name == person.name
    }

}

fun main() {
//    重写hashcode  和  equals  demo
    val persons = HashSet<Person>()

    (0..5).forEach {
//        +=  对应的运算符为 plusAssign  调用了add方法
        persons += Person(20, "zxf")
    }

    println(persons.size)

//    重要!!!   重写hashcode方法后,修改成员字段数值会影响hashcode值,进而影响到对象在哈希表中的位置,致使remove方法无法找到原来的对象,但是,对象有在哈希表中有引用,hash对象又没有被释放。垃圾回收器发现其还有引用,又不会回收该对象。于是,内存泄漏了。
//    重写hashcode方法的类对象,在放入hash表后,一定要谨慎操作对象字段属性值。如果要修改,先从哈希表中删除该对象,修改后再放入哈希表。

    val person = Person(20, "zxf")
    persons += person

    println("移除前${persons.size}")
//    改变内部数据
    person.age = 21
//    调用 minusAssign 即remove  没有效果  容易造成内存泄露
    persons -= person

    println("移除后${persons.size}")

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

pumpkin的玄学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值