Kotlin 语法上的一些亮眼操作

本文介绍了Kotlin语言相较于Java的一些独特之处,包括函数扩展、空安全特性、智能转换及安全转换等功能,展示了Kotlin在简洁性和安全性上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kotlin 语法上的一些亮眼操作

Kotlin 初体验

写在前面:
上上周我们创建了第一个 kotlin 的 android 应用。上周我花了一周的时间,在工作之余了解了 kotlin 的语法。感叹 kotlin 做为“高级”语言与 java相比,展现出来的简洁、高效、智能。不过如果有人问我 kotlin 和 java 的具体区别,那我肯定会首先描述为 命令式编程语言函数式编程语言 的区别。

命令式编程语言函数式编程语言 用概念描述,可以为:命令式编程语言泛指所有把修改变量的值当作最基本计算方式的语言,函数式编程语言指把一个程序的输出定义为其输入的数学函数的语言,纯函数式编程没有内部状态的概念,也没有副作用。

对两者而言,我的体会并不深刻,所以来引用知乎的一段话:

纯函数式编程语言中的变量也不是命令式编程语言中的变量,即存储状态的单元,而是代数中的变量,即一个值的名称。变量的值是不可变的(immutable),也就是说不允许像命令式编程语言中那样多次给一个变量赋值。比如说在命令式编程语言我们写“x = x + 1”,这依赖可变状态的事实,拿给程序员看说是对的,但拿给数学家看,却被认为这个等式为假。

函数式语言的如条件语句,循环语句也不是命令式编程语言中的控制语句,而是函数的语法糖,比如在Scala语言中,if else不是语句而是三元运算符,是有返回值的。

关于二者的比较可以进一步查阅资料来了解,对于理解编程语言的本质和计算机的构成,很有帮助。

下面我们就来看看与 java 相比,kotlin 有哪些“高级”的语法。

函数扩展

        val array: Array<Int> = arrayOf(4, 5, 6)
        val array3: Array<Int> = arrayOf(7, 8, 9)
        // 声明一个函数扩展,我们需要在函数前加一个接收者类型作为前缀。上面就是为 `Array<Int>` 添加一个 swap 函数
        fun Array<Int>.swap(x: Int, y: Int) {
            // 在扩展函数中的 this 关键字对应接收者对象。
            val temp: Int = this[x]
            this[x] = this[y]
            this[y] = temp
        }
        // 可以在任何 Array<Int> 实例中使用这个函数了
        array.swap(1, 2)
        array3.swap(0, 3)

如果用 java 来做的话,我们需要继承父类。或者用一个方法做这个操作,需要将 array 作为参数传递进去,这样一来就加大了出错概率,也不够自由美观,这就是扩展带来的好处。

空安全

导致 java 程序崩溃最多的 Exception 就是 NullPointerException 也叫 NPE,Kotlin 类型系统致力与消灭它。

在 Kotlin 类型系统中可以为空和不可为空的引用是不同的。比如,普通的 String 类型的变量不能为空:

        var s: String = "activity"
        s = null //编译报错 普通字符串类型不可为空

        var t:String? = "fragment"
        t = null //同?声明的 String 可以为空

        print(s.length)// 可以调用,这里的 s 永不为 null
        print(t.length)// 报错,这里的 t 可能为空

可以看到,这里在声明一些可能为 null 的引用时,kotlin 是区分对待的,并且在调用的时候自动判断它是否可能为 null,当可能为空的时候,直接用 . 调用,会直接报错。

如果我们想调用,可以用条件判断的方式:

        val u = if (t != null && t.length > 0) {
            print(t.length)
            t.length
        } else {
            -1
        }

这样显然稍显啰嗦,kotlin 自然想到了这一点,这样安全操作符 ?. 就出现了。

        val r: Int? = t?.length

这个表达式,当 t 为 null 时,返回 null,否则返回 t.length

安全调用在链式调用是是很有用的。比如,如果 Bob 是一个雇员可能分配部门(也可能不分配),如果我们想获取 Bob 的部门名作为名字的前缀,就可以这样做:

    bob?.department?.head?.name //这样的调用链在任何一个属性为空都会返回空

如果用 java 来做,那就会完全体现 java 的“又臭又长”了

Elvis 操作符
?: Elvis 操作符表达的是,当左边表达式为空时,会执行右边的表达式。否则执行左边的表达式。

        val o = t?.length ?: -1
        val i = t?.length ?: throw NullPointerException()

!! 表达式

        val y = t!!.length

当 t 为 null 时,抛出一个 NPE,否则返回 t 的长度值。

智能转换

is !is 表达式

    fun smartCast(any: Any) {
        if (any is String) {
            println(any.length)// x is automatically cast to String
        }
    }

通过 is 关键字,在 if 表达式中,any 已经自动被转换成了 String 类型。

安全转换 as?

        val s: String? = any as? String

若 any 为 null 时,显然是不可以转换成 String 的,这时候用 as? 安全转换,如果失败了,则返回 null。

字符串模板

        val firstName = "Android"

        val lastName = "Studio"

        println("his name is $firstName $lastName")

如上所示,kotlin 可以用 $ 将一些值直接连接在字符串当中

单例模式

在 java 中,我们创建一个单例模式的对象可能是这样子的:

public class Utils {

    private Utils() { 
      // This utility class is not publicly instantiable 
    }

    public static int getScore(int value) {
        return 2 * value;
    }

}

在 kotlin 中,就方便了很多:

object Utils {

    fun getScore(value: Int): Int {
        return 2 * value
    }

}

Bean 对象

在 java 中创建一个 bean 对象,可能是这样的:

public class Developer {

    private String name;
    private int age;

    public Developer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Developer developer = (Developer) o;

        if (age != developer.age) return false;
        return name != null ? name.equals(developer.name) : developer.name == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Developer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在 kotlin 中,可以使用 data 关键字,直接创建一个 bean 对象:

data class Developer(var name: String, var age: Int)

Ranges

kotlin 还有一些特有的属性,比如类型的推断啊,一级构造函数啊,等等。这些自己去撸文档就可以了,最后一个想说的就是 kotlin 中的 Ranges 属性。

Ranges 操作符是由 in 关键字实现的:

if (i in 1..10) {
    println(i) // 打印 1 - 10 闭区间
}

if (x !in 1.0..3.0) println(x)

if (str in "island".."isle") println(str)

当然还有更多的用法和关键字,根据打印值体会:

for (i in 1..4 step 2) print(i) // prints "13"

for (i in 4 downTo 1 step 2) print(i) // prints "42"

for (i in 1.0..2.0 step 0.3) print("$i ") // prints "1.0 1.3 1.6 1.9 "

好了本文对 kotlin 一些我认为很亮眼的语法和用法就介绍完成了,下一步我打算研究下 kotlin 在快速开发 android 上,有哪些黑科技。

### 2025年1月流行编程语言排行榜 在2025年1月,根据TIOBE指数发布的数据,Python荣膺TIOBE 2024年度编程语言称号[^1]。这表明Python不仅保持了强劲的发展势头,在多个应用领域也获得了广泛的认可。 #### 排名前三的语言 - **Python**:作为最受欢迎的编程语言之一,Python凭借其简洁易读的语法以及强大的社区支持持续占据榜首位置[^2]。 - **C**:作为一种经典的系统级编程语言,C以其高效性和稳定性位居第二位。尽管面临诸多新兴语言的竞争压力,但在操作系统开发等领域依然不可或缺。 - **Java**:由于企业级应用程序和Android移动平台的支持,Java稳居第三的位置不变。它拥有庞大的开发者群体及丰富的库资源。 #### 其他值得关注的语言 除了上述三种主流语言外,还有几门表现亮眼编程语言值得特别关注: - **Go**:由Google推出并维护,因其出色的并发处理能力和高效的编译速度而受到越来越多企业的青睐。 - **PHP**:虽然近年来有所下滑但仍不可忽视,特别是在Web后端服务构建方面有着广泛应用基础。 - **Rust** 和 **Kotlin**:这两者分别以安全内存管理和现代化特性设计著称,正逐步扩大市场份额,成为未来发展的潜力股。 这些排名反映了当前软件行业对于不同技术栈的需求趋势,同时也体现了各编程语言自身特点和发展方向的选择影响着它们的地位变化[^3]。 ```python # Python 示例代码展示其简单优雅的特点 def greet(name): return f"Hello, {name}!" print(greet("World")) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值