Kotlin基础——基础内容

文章目录

  • 1 函数和变量
    • 1.1 基本程序
    • 1.2 函数
    • 1.3 变量
      • 1.3.1 变量的类型推导
      • 1.3.2 可变变量和不可变量
      • 1.3.3 变量使用规则
    • 1.4 字符串模板
  • 2 类和属性
    • 2.1 属性
    • 2.2 自定义访问器
    • 2.3 目录和包
      • 2.3.1 同包访问
      • 2.3.2 不同包导入
      • 2.3.3 包名类名定义规则
  • 3 枚举和“when”
    • 3.1 声明枚举类
    • 3.2 when结构使用
    • 3.3 when结构包含对象
    • 3.4 使用不带参数的“when”
    • 3.5 合并类型检查和转换
    • 3.6 用“when”代替“if”
    • 3.7 代码块作为“when”的分支
  • 4 循环语句
    • 4.1 while循环
    • 4.2 for循环
    • 4.3 迭代map
    • 4.4 使用“in”检查集合和区间成员
  • 5 异常
    • 5.1 抛异常和捕获异常
    • try作为表达式

1 函数和变量

1.1 基本程序

fun main(args: Array<String>) {
    println("Hello World!")
}

程序从“Hello World”打印开始,从这个简单的程序中,包含Kotlin语言的以下特性:

  • 函数使用关键字fun声明
  • 主函数依然为main函数
  • Kotlin中没有Java中数组类型,数组就是Array类
  • 函数可以定义在文件的最外层,可以不用放到类中
  • 参数类型在参数的后面
  • Java中的很多语句Kotlin做了更简易的封装,比如println
  • 语句结尾不需要分号

1.2 函数

fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

函数仍然由函数名,参数列表和返回值类型组成。不同的是函数使用fun定义,参数类型和返回值类型在后面

  • Kotlin不支持三元运算符(?😃
  • Kotlin中很多逻辑运算是表达式,可以直接返回值

上面的可以简化为:

fun max(a: Int, b: Int): Int = if (a > b) a else b

这样的函数拥有表达式体,上面有大括号的函数拥有代码块体。
还可以进一步简化为:

fun max(a: Int, b: Int) = if (a > b) a else b

对于拥有表达式体的函数,可以省略其返回值类型,因为Kotlin具有类型推导能力。

1.3 变量

Java中声明变量从类型开始,而Kotlin中很多时候不需要声明变量的类型,因为Kotlin有强大的类型推导功能,能够根据上下文推导出具体的类型。

1.3.1 变量的类型推导

val a = 10
val b = 12.3
val c = "test"

a被推导为Int类型
b被推导为Double类型
c被推导为String类型
Kotlin中没有Java中的基本数据类型,所有类型都是类对象
如果要显示指定数据的类型,可以在变量后面加变量的类型

val d: Byte = 10

1.3.2 可变变量和不可变量

Kotlin中通常有两个变量修饰符

  • val(value):不能在初始化后再次赋值,对应于Java中使用final修饰的变量
  • var(variable):可变变量,对应于Java中的非final修饰符

默认情况下,应该首先使用val修饰符,当变量确实需要改变时,才替换成var修饰符

1.3.3 变量使用规则

在这里插入图片描述
val类型赋值之后不可改变,否则编译不过
在这里插入图片描述
如果变量不在定义的时候初始化,则需要确定其类型,因为Kotlin虽然可以类型推导,但还是静态类型的语言,每个变量都有确定的类型。不在定义的时候确定其类型,编译器无法推导,无法编译通过

val b: Int
if (a > 5) {
    b = 1
} else {
    b = 0
}

val变量只能赋值一次,如果编译器能够保证只执行一条初始化语句,则可以编译通过

val list = listOf(1, 3, 4)
list.addLast(5)

val变量定义的引用不可变,但是其引用对象的内容可变。list指向一个List对象,不能改变其引用直系指向,但是该List对象可以改变其中存储的元素
在这里插入图片描述
对于var可变类型变量,不能改变其数据类型,当a定义的时候,类型推导为Int类型,此时该变量的类型就已经被确定,不能改变其类型,否则编译失败

1.4 字符串模板

开发中很多时候涉及到字符串拼接,Java中拼接如下

"Hello, " + name + "!"

在Kotlin中可以使用更简便的写法,就是字符串模板

"Hello, $name!"

字符串模板不止可以引用简单变量,还可以引用复杂的变量

val names = listOf("World", "Kotlin")
println("Hello, ${names[0]}!")

这里可以使用大括号引用字符串数组的第一个元素

println("Hello, ${if (args.size > 0) args[0] else "World"}!")

大括号中还可以嵌套表达式

2 类和属性

Kotlin也是面向对象的语言,是JVM语言,在Java虚拟机上运行,所以也是有类和属性一说
Java中有一个JavaBean的概念,表达的是一种Java中规范类的写法

public class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

通常这些构造函数和get方法都是比较重复的代码,与具体的业务逻辑无关
可以将上面的代码拷贝到kotlin文件中,能够自动将Java代码转换成kotlin代码

class Person(val name: String)

Kotlin中只需要一行代码就能够表示上面的一段Java代码
public类修饰符消失了,因为在Kotlin中public是默认的可见性

2.1 属性

类的概念是把数据和处理数据的代码封装成一个单一的实体
类包含属性和行为,在Java中字段和访问器(settergetter)的组合常常被叫做属性
Kotlin中,属性是头等的语言特性,完全替代了字段和访问器方法
在类中声明一个属性和声明一个变量一样:使用val和var关键字,当声明属性的时候,就默认声明了对应的访问器。声明成val的属性是只读的,默认会提供对应的get方法,而声明成var的属性是可变的,默认会提供getset方法

class Person(val name: String, var isMarried: Boolean)

这里声明了两个属性,一个是只读属性,只提供getter方法,另一个是可变属性,提供gettersetter方法,使用Java访问Kotlin声明的类

public class Test {
    public static void main(String[] args) {
        Person person = new Person("zhangsan", false);
        person.setMarried(true);
        System.out.println(person.getName());
        System.out.println(person.isMarried());
    }
}

输出

zhangsan
true

Kotlin声明的属性,是一个类的字段都是私有的类,在Java代码中可以访问Kotlin声明的类,可以看到,声明为val的属性,只有getter方法,声明为var的属性,有gettersetter方法。
如果属性声明为XXX,默认提供的是setXXXgetXXX方法,其中有一个例外是isXXX开头的属性,这种属性,默认提供的是setXXXisXXX方法,需要注意。
上面是Java中访问Kotlin中声明的类,下面代码为Kotlin中访问

fun main(args: Array<String>) {
    val person = Person("zhangsan", false)
    person.isMarried = true //1
    println(person.name) //2
    println(person.isMarried)
}

上面的Kotlin代码中,看起来像是直接访问的定义的属性。但是上面说过,Kotlin中声明的属性变量,默认是private的,Kotlin中也没有改变类中private变量无法从类外访问的特性。Kotlin中,不需要显示调用gettersetter方法,而是像访问public属性一样调用访问器。注释1处默认调用的是person对象的isMarried类变量的setter方法,而注释2处则是调用的getter方法。

2.2 自定义访问器

上面属性默认的访问器都是编译器生成的,而如果要实现自己的逻辑,就需要自己自定义访问器

class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() {
            return height == width
        }
}

Rectangle类定义了一个属性isSquare,该属性用val修饰,只提供getter方法,而这个getter方法没有使用默认的getter,而是使用自定义的getter方法。自定义访问器就是对属性创建一个get函数或者set函数来自定义getter方法和setter方法。

2.3 目录和包

kotlin文件中以package语句开头,文件中定义的所有声明(类、函数、属性)都在该包中,如果其他文件中定义了相同的包,则他们属于同一包中,可以直接使用,如果包不同,则需要导入,导入使用import关键字。

2.3.1 同包访问

TestOne

package com.test

class TestOne(val num: Number)

fun TestOnePrint() {
    println("TestOnePrint")
}

TestTwo

package com.test

class TestTwo(){
}

fun main() {
    val testOne = TestOne(3)
    TestOnePrint()
}

TestTwo文件中的main函数可以直接访问TestOne文件中。
与Java不同的是Java中包路径与项目的实际路径对应,一个点是一个文件夹,而在Kotlin中,包名可以不与文件路径相对应,可以将该文件放到项目中的任意位置,但是他们仍处于相同的包下,且不会导致编译错误。

2.3.2 不同包导入

Kotlin中import可以导入任何声明
导入顶层函数

import com.test.TestOnePrint

导入类

import com.test.TestOne

导入包中所有元素

import com.test.*

2.3.3 包名类名定义规则

类名:
首先来看Java,Java中一个类文件可以包含多个类定义,但是只能有一个public定义的,且必须和类文件相同。
而对于Kotlin来说,则没有这么严格的显示,同样的,一个文件中可以定义多个类,类文件文件名可以任意选择。
包名:
对于包名来说,虽然Kotlin没有限制,但是建议参考Java中的实现方式,能够使代码结构更加清晰

3 枚举和“when”

3.1 声明枚举类

enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}

kotlin中创建枚举类比Java多一个关键字,需要enum class一起使用,enum是一个软关键字,只有放在class前面才有意义。

3.2 when结构使用

fun printColor(color: Color) {
    when (color) {
        Color.RED -> println("red")
        Color.BLUE -> println("blue")
        Color.VIOLET -> println("violet")
        else -> println("no such color")
    }
}

kotlin中没有switch...case,kotlin中多重判断使用when结构。

fun getWarmth(color: Color) = when (color) {
    Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
    Color.GREEN -> "neutral"
    Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}

when结构也可以合并处理
需要注意的是when结构使用枚举类的时候,需要对所有变量进行定义,或者定义else,否则无法编译通过

3.3 when结构包含对象

when结构比switch更加强大,switch只能使用常量(枚举常量、字符串常量或者数字字面量),而when结构可以使用任何类型对象

fun max(c1: Color, c2: Color) = when (setOf(c1, c2)) {
    setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
    setOf(Color.YELLOW, Color.BLUE) -> Color.GREEN
    setOf(Color.BLUE, Color.VIOLET) -> Color.INDIGO
    else -> throw Exception("Dirty color")
}

这里使用when结构,包含的是一个set对象

3.4 使用不带参数的“when”

when结构可以不带参数

fun mixOptimized(c1: Color, c2: Color) {
    when {
        (c1 == Color.RED && c2 == Color.YELLOW) ||
                (c1 == Color.YELLOW && c2 == Color.RED) ->
            Color.ORANGE

        (c1 == Color.BLUE && c2 == Color.YELLOW) ||
                (c1 == Color.YELLOW && c2 == Color.BLUE) ->
            Color.GREEN

        (c1 == Color.BLUE && c2 == Color.VIOLET) ||
                (c1 == Color.VIOLET && c2 == Color.BLUE) ->
            Color.INDIGO

        else -> throw Exception("Dirty color")
    }
}

如果没有提供when的参数,分支条件就是任意的布尔表达式

3.5 合并类型检查和转换

Java中,用于判断对象是否是一个类的实例,需要使用instanceof关键字。通常传入的参数是父类类型时,需要转换成子类类型,还需要使用强转。

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

fun eval(e: Expr): Int {
    if (e is Num) {
        val n = e as Num
        return n.value
    }
    if (e is Sum) {
        return eval(e.left) + eval(e.right)
    }
    throw IllegalArgumentException("Unknown expression")
}

上面是类似于Java中的写法,is关键字用于判断对象是否是Num类对象,相当于instanceof。as关键字用于强转。
但是Kotlin中合并了类型检查和转换

val n = e as Num

这一行是不需要的,因为is关键字在检查的时候,如果返回true,就自动的将e转换成了Num对象

3.6 用“when”代替“if”

上面的例子可以使用when结构进行改造

fun eval(e: Expr): Int =
    when (e) {
        is Num -> e.value
        is Sum -> eval(e.left) + eval(e.right)
        else -> throw IllegalArgumentException("Unknown expression")
    }

直接返回when运算的值,这里的when结构中,用于判断对象类型。

3.7 代码块作为“when”的分支

fun evalWithLogging(e: Expr): Int =
    when (e) {
        is Num -> {
            println("num : ${e.value}")
            e.value
        }

        is Sum -> {
            val left = evalWithLogging(e.left)
            val right = evalWithLogging(e.right)
            println("sum: $left + $right")
            left + right
        }

        else -> throw IllegalArgumentException("Unknown expression")
    }

when结构的分支中可以是代码块。这里由于when直接充当返回值,所以各个分支的最后一行就是返回值

4 循环语句

Kotlin支持两种循环:while循环和for循环

4.1 while循环

语法

while (condition) {
	...
}

do {
	...
} while (condition)

4.2 for循环

Kotlin中的for循环和Java中不太一样,使用的是区间和数列
区间:
表示两个范围内的数,使用..运算符

val oneToTen = 1..10

这个区间是一个闭合的区间,两边临界都能取到

for (i in 0..10) {
    println(i)
}

使用for循环遍历0到10,i不需要提前定义,这里使用的时候就直接定义了

for (i in 0..10 step 2) {
    println(i)
}

可以使用step跳过其中的一些值

for (i in 10 downTo 0 step 2) {
   println(i)
}

可以使用downTo做倒序的遍历

for (i in 0 until 10) {
    println(i)
}
for (i in 0 ..<10) {
    println(i)
}

可以使用until关键字或者..<来做一个左闭右开的区间

4.3 迭代map

循环常用的就是用来遍历集合

val binaryReps = TreeMap<Char, String>()
for (c in 'A'..'F') {
    val binary = Integer.toBinaryString(c.code)
    binaryReps[c] = binary
}
for ((letter, binary) in binaryReps) {
    println("$letter = $binary")
}

map添加元素可以使用使用赋值这种简写方式,遍历的时候可以将key-value展开到两个变量中

val list = arrayListOf("10", "12", "2343")
for ((index, element) in list.withIndex()) {
    println("$index = $element")
}

遍历的时候也可以不用定义索引值,而是通过withIndex获取

4.4 使用“in”检查集合和区间成员

使用in检查元素是否在其中或者!in检查元素是否不在其中

fun isLetter(c: Char) = c in 'a' .. 'z' || c in 'A' .. 'Z'
fun inNotDigit(c: Char) = c !in '0' .. '9'

这两个判断也适用于when表达式

fun recognize(c: Char) = when (c) {
    in '0'..'9' -> "It's a digit"
    in 'a'..'z', in 'A'..'Z' -> "It's a letter"
    else -> "I don't know"
}

5 异常

5.1 抛异常和捕获异常

Kotlin中的异常和Java中相似,一个函数可以正常结束,也可以抛出异常。异常可以处理,也可以向上抛出。
抛出异常:

if (percentage !in 0 .. 100) {
	throw IllegalArgumentException("Invalid percentage")
}

捕获异常

fun readNumber(reader: BufferedReader): Int? {
    try {
        val line = reader.readLine()
        return Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        return null
    } finally {
        reader.close()
    }
}

同样使用try...catch...finally结构

try作为表达式

Kotlin中try可以作为表达式

fun readNumber(reader: BufferedReader): Int? =
    try {
        val line = reader.readLine()
        Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        null
    } finally {
        reader.close()
    }

try是一个表达式,可以直接返回,运算中的最后一行就是返回值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/237554.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试之压力测试详解

一、什么是压力测试 软件测试中&#xff1a;压力测试&#xff08;Stress Test&#xff09;&#xff0c;也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷&#xff0c;长时间或超大负荷地运行测试软件&#xff0c;来测试被测系统的性能、…

leetcode-19-删除链表的倒数第N个节点

题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示…

深度学习 Day15——P4猴痘病识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言1 我的环境2 代码实现与执行结果2.1 前期准备2.1.1 引入库2.1.2 设置GPU&#xff08;如果设备上支持GPU就使用GPU,否则使用C…

Swagger快速上手

快速开始&#xff1a; 导入maven包 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version> </dependency><dependency><groupId>io.springfox<…

UDS DTC故障码格式

文章目录 DTC的定义DTC 故障码的分类DTC 故障码的组成1、OBD DTC 格式结构2、UDS DTC&#xff08;ISO 14229-1、ISO 15031-6&#xff09;格式结构 参考 DTC的定义 DTC&#xff0c;Diagnostic Trouble Code&#xff0c;诊断故障码&#xff0c;即 故障类型的 ID。 一个完整的DT…

【快速应用开发】看看RedwoodJS

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

CommonJs模块化实现原理ES Module模块化原理

CommonJs模块化实现原理 首先看一个案例 初始化项目 npm init npm i webpack -D目录结构如下&#xff1a; webpack.config.js const path require("path"); module.exports {mode: "development",entry: "./src/index.js",output: {path: p…

VBA信息获取与处理:在EXCEL中随机函数的利用

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

助力工业生产质检,基于轻量级yolov5-seg开发构建工业场景下滚珠丝杠传动表面缺陷分割检测系统

AI赋能工业生产是一个强有力的方式&#xff0c;在我们之前的系列博文中也有很多相应的开发实践&#xff0c;感兴趣的胡都可以自行移步阅读&#xff0c;本文的核心思想就是想要基于轻量级的实例分割模型来开发构建工业场景下的滚珠丝杠传动表面缺陷分割检测系统&#xff0c;首先…

Openwrt源码下载出现“The remote end hung up unexpected”

最近项目原因需要下载openwrt21.02版本源码&#xff0c;花费了很多时间&#xff0c;找到正确方法后&#xff0c;发现可以节省很多时间&#xff0c;记录下过程&#xff0c;方便自己&#xff0c;可能方便他人。 一.问题阐述 openwrt21.02下载链接如下&#xff1a; git clone -…

Springboot入门篇

一、概述 Spring是一个开源框架&#xff0c;2003 年兴起的一个轻量级的Java 开发框架&#xff0c;作者Rod Johnson 。Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 1.1对比 对比一下 Spring 程序和 SpringBoot 程序。如下图 坐标 Spring 程序中的…

【华为数据之道学习笔记】3-11元数据管理

1. 产生元数据 &#xff08;1&#xff09;明确业务元数据、技术元数据和操作元数据之间的关系&#xff0c;定义华为公司元数据模型。 &#xff08;2&#xff09;针对找数据及获取数据难的痛点&#xff0c;明确业务元数据、技术元数据、操作元数据的设计原则。 1&#xff09;业务…

Pytorch-LSTM轴承故障一维信号分类(一)

目录 前言 1 数据集制作与加载 1.1 导入数据 第一步&#xff0c;导入十分类数据 第二步&#xff0c;读取MAT文件驱动端数据 第三步&#xff0c;制作数据集 第四步&#xff0c;制作训练集和标签 1.2 数据加载&#xff0c;训练数据、测试数据分组&#xff0c;数据分batch…

C++之STL算法(1)

STL容器算法主要由、、组成&#xff1b;   algorithm主要有遍历、比较、交换、查找、拷贝、修改等&#xff1b; 1.遍历容器for_each for_each()函数用于完成容器遍历&#xff0c;函数参数如下&#xff1a; for_each(_InIt _First, _InIt _Last, _Fn _Func) 形参&#xff1a…

mybatis多表映射-延迟加载,延迟加载的前提条件是:分步查询

1、建库建表 create database mybatis-example; use mybatis-example; create table t_book (bid varchar(20) primary key,bname varchar(20),stuid varchar(20) ); insert into t_book values(b001,Java,s001); insert into t_book values(b002,Python,s002); insert into …

基于 librosa和soundfile对音频进行重采样 (VITS 必备)

基于 librosa和soundfile对音频进行重采样 一、前言 在玩bert-vits2的时候有对音频进行重采样的需求&#xff0c;故写了一下批量对音频进行重采样的脚本。 优化点&#xff1a; 根据机器自适应线程数为最多&#xff0c;保证充分利用机器资源&#xff0c;提高速度>30%。支持…

UE引擎 LandscapeGrass 实现机制分析(UE5.2)

前言 随着电脑和手机硬件性能越来越高&#xff0c;游戏越来越追求大世界&#xff0c;而大世界非常核心的一环是植被&#xff0c;目前UE5引擎提供给植被生成的主流两种方式为 手刷植被和LandscapeGrass(WeightMap程序化植被)。当然UE5.3推出新一代PCGFramework 节点程序化生成框…

Android 顶部对齐宽度撑满高度等比例缩放及限制最大最小高度

一 示例 二 代码 <?xml version"1.0" encoding"utf-8"?> <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent&qu…

点评项目——秒杀优化

2023.12.11 上一张的秒杀券下单还可以进行优化&#xff0c;先来回顾一下下单流程&#xff1a; 可以看出流程设计多次查询和操作数据库的操作&#xff0c;并且执行顺序是一个线程串行执行&#xff0c;执行性能是比较低的。 优化方案&#xff1a;我们将判断秒杀库存和校验一人一单…

蓝桥杯周赛 第 1 场 强者挑战赛 6. 小球碰撞【算法赛】(思维题/最长上升子序列LIS)

题目 https://www.lanqiao.cn/problems/9494/learning/?contest_id153 思路来源 Aging代码 题解 二分时间t&#xff0c;第i个小球对应一个起点pi、终点pit*vi的区间&#xff0c;问题转化为&#xff0c; 选最多的区间&#xff0c;使得不存在区间包含&#xff08;即li<l…
最新文章