第二章(Kotlin基础)

基本要素:函数和变量

函数

函数定义规则

  • 函数通过关键字?fun?用来声明一个函数
  • 参数的类型与函数返回类型写在它的名称后面,这和变量声明一样
  • 函数可以定义在文件的最外层,不一定要把它放在类中

示例:

fun max(a: Int, b: Int): Int {
  return if (a > b) a else b
}
>>> println(max(1,2))  //打印结果:2

函数的声明以关键字 fun?开始,函数名称紧随其后:上面示例中函数名称是max,接下来是括号括起来的参数列表。参数列表后面跟着返回类型,它们之间用一个冒号隔开。如果不需要返回类型,则可以直接省略冒号及其后面的返回类型。
在Kotlin中,if?是有结果值的表达式。如上示例代码中函数的返回值 if (a > b) a else b ,它和Java中的三元运算符相似:(a>b) ? a : b。Kotlin中,if?是表达式,而不是语句。表达式和语句的区别在于,表达式有值,并且能作为另一个表达式的一部分使用;而语句总是包围着它的代码块中的顶层元素,并且没有自己的值。

表达式函数体

上面示例代码可以变得更简单。因为它的函数体是由单个表达式构成的,可以用这个表达式作为完整的函数体,并去掉花括号和return语句。如果函数体写在花括号中,我们说这个函数有代码块体。如果它直接返回了一个表达式,那么这个函数就有表达式体。

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不是要求每个表达式都应该在编译器具有类型吗?事实上,每个变量和表达式都有类型,每个函数都有返回类型。但是对表达式函数体来说,编译器会分析作为函数体的表达式,并把它的类型作为函数的返回类型。这也是Kotlin的类型推导。(注意:只有表达式体函数的返回类型可以省略。对于有返回值的代码块函数体,必须显示地写出返回类型和return语句。)

变量

Kotlin中声明变量的关键字有两个:

  • val(来自value)—?不可变引用。使用val声明的变量不能在初始化之后再次赋值。它对应的是Java的final变量。
  • var(来自variable)—?可变引用。使用var声明的变量的值可以被改变。这种声明对应的是普通(非final)的Java变量。

默认情况下,应该尽可能地使用val关键字来声明所有的Kotlin变量,仅在必要的时候换成var。
注意:尽管val引用自身是不可变的,但是它指向的对象可能是可变的。例如:下面这段代码是完全有效的:

val languages = arrayListOf("Java") //声明不可变引用
languages.add("Kotlin") //改变引用指向的对象

字符串模板($)

Kotlin中的字符串模板相当于Java中的“+”号,示例:

val name = "World"
//下面两行代码是等效的
println("Hello "+name)
println("Hello $name")

>>> 打印结果:Hello World

类和属性

Kotlin中类声明比Java中更简洁。我们以一个简单的JavaBean类来对比,以下两个例子完全等效,只是分别用Java与Kotlin来声明。

/* Java */
public class Person {
  private final String name;

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

  public String getName() {
    return name;
  }
}
/* Kotlin */
class Person(val name: String)

属性

在Java中,字段和其访问器(getter,setter)的组合常常被叫做属性。而在Kotlin中,属性是头等的语言特性,完全代替了字段和访问器方法(getter和setter方法),在类中声明一个属性和声明一个变量一样:使用val和var关键字。声明成val的属性是只读的(只有getter方法),声明成var属性是可变的(包含getter和setter方法)。

示例:

class Person(val name: String, var age: Int) //Person类声明了一个只读的name属性与可变的age属性

fun main(args: Array<String>) {
    val person = Person("xiaochao",24)
//    person.name = "xiaochao" //编译不通过,val修饰,是只读的(只有getter,没有setter),不可修改
    person.age = 25//编译通过,var修饰,是可变的,这里赋值是调用setter方法
    println("name=${person.name},age=${person.age}")//这里取值是调用getter方法
}
>>> 打印结果:name=xiaochao,age=25

上面代码演示了在构造函数中声明属性及调用,如果想直接在Person类文件中声明属性也是一样的。

class Person {
    val name: String = "xiaochao"
    var age: Int = 0
}

fun main(args: Array<String>) {
    val person = Person()
//    person.name = "hello world" //编译不通过,name是val修饰的,是只读的,不可修改
    person.age = 18
    println("name=${person.name},age=${person.age}")
}
>>> 打印结果:name=xiaochao,age=18

自定义访问器(getter、setter)

假设你声明这样一个矩形,它能判断自己是否是正方形。不需要一个单独的字段来存储这个信息(是否是正方形),因为可以随时通过检查矩形的长宽是否相等来判断:

class Rectangle(val height:Int,val width:Int){
//    val isSquare:Boolean
//       //自定义getter方法,同理也可以自定义setter方法,不过要自定义setter方法则属性必须声明为var类型
//        get() {
//            return height==width
//        }

    //可以使用表达式函数体来简化
    val isSquare:Boolean
        get() = height==width
}

fun main(args: Array<String>) {
    val rectangle = Rectangle(20,20)
    println(rectangle.isSquare)
}
>>> 打印结果:true

枚举和“when”

声明枚举类

和Java一样,枚举并不是值的列表:可以给枚举声明属性和方法。

enum class Color(val r: Int, val g: Int, val b: Int) {

    //下面每一个颜色都表示一个Color枚举类常量
    RED(255, 0, 0), YELLOW(255, 255, 0),
    ORANGE(255,165,0),INDIGO(75,0,130),
    GREEN(0, 255, 0), BLUE(0, 0, 255);//这里必须要有分号

    fun rgb() = (r * 256 + g) * 256 + b//给枚举类定义一个方法
}

fun main(args: Array<String>) {
    println(Color.BLUE.rgb())
}
>>> 打印结果:255

when的基本使用

fun getMnemonic(color:Color){
    when(color){
        Color.RED -> println("red")
        Color.BLUE -> {
            println("blue")
        }
        Color.GREEN,Color.YELLOW -> println("green or yellow")
    }
}

when当作表达式函数体

使用when当作表达式函数体时,when中的分支都必须在最后加else判断(在这里判断条件Color是枚举类型,所以这里将枚举类型的所有常量声明完整也可以省略else,其他情况下则必须加else):

fun getMnemonic2(color:Color) =
        when(color){
            Color.RED -> "RED"
            Color.BLUE -> {
               "BLUE"
            }
            Color.GREEN,Color.YELLOW -> "GREEN or YELLOW"
          //如果不加else则编译无法通过,因为Color下还有ORANGE与INDIGO没判断
            else -> "other"
        }

不带参数的when

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

fun mixOptimized(color1:Color,color2:Color) =
        when{
            (color1==Color.RED && color2==Color.YELLOW) ||
                    (color1==Color.YELLOW && color2==Color.RED) -> Color.ORANGE
            (color1==Color.YELLOW && color2==Color.BLUE) ||
                    (color1==Color.BLUE && color2==Color.YELLOW) -> Color.GREEN
           else -> throw Exception("Dirty color")
        }

智能转换:合并类型检查和转换

如果你检查过一个变量是某种类型,后面就不再需要转换它,可以就把它当作你检查过的类型使用。事实上编译器为你执行了类型转换,我们把这种行为称为智能转换,智能转换只在变量经过 is 检查之后且不再发生变化的情况下有效。例子:

private val view:View? = null
fun  test(){
    if(view is TextView){
        view.setText("这里view已经可以当成TextView使用")
    }
}

智能转换通过 is关键字来表示,这里的 is相当于Java中的 instanceof

强制转换则通过 as关键字来表示,例子:

private val view:View? = null
fun  test(){
    val textview = view as TextView
    textview.setText("强制转换")
}

for循环

for循环基本使用

for (i in 0..10) { //从0开始遍历到10
    println(i)//0,1,2,3,4,5,6,7,8,9,10
}

上面我们看到了最简单的for循环的使用方式,Kotlin中的for循环是用区间来表示,使用.. 运算符来表示区间,上面的for循环就表示0到10这个区间。除了区间这个概念,Kotlin中的for循环还涉及到步长这个概念。步长简单理解就是每次循环区间的大小,默认是1,如上面的代码,没有显示指定步长,默认就是从0到10这个区间以1的步长递增循环,接下来我们指定步长为2,那么输出的结果就会是0,2,4,6,8,10。以2的步长去递增。看下面代码:

for (i in 0..10 step 2) {
    println(i)//0,2,4,6,8,10
}

如果我们想从10递减到0那么该怎么写呢?看下面代码:

for (i in 10 downTo 0) {  //这里我们同样可以设置步长
    println(i)
}

上面我们通过0..10知道了for循环的区间,这样会打印出0到10,接下来我们再看一种Kotlin中for循环写法:

for (i in 0 until 10){
    println(i)//0,1,2,3,4,5,6,7,8,9
}

注意上面until这种写法与0..10的区别在与until这种写法只会打印0到9,而0..10则会打印0到10。

迭代数字:区间和数列

区间本质上就是两个值之间的间隔,这两个值通常是数字:一个起始值,一个结束值。使用 ..?运算符来表示区间:

val oneToTen = 1..10

注意Kotlin的区间是包含的或者闭合的,意味着第二个值始终是区间的一部分。
你能用整数区间做的最基本的事情就是循环迭代其中所有的值。如果你能迭代区间中所有的值,这样的区间被称作数列。

for循环迭代map

val maps = TreeMap<Char, String>()
for (c in 'A'..'F') {
    val value = Integer.toBinaryString(c.toInt() )//A-F的二进制值
    maps[c] = value //c为键,value为值
}
for ((key, value) in maps) {
    println("$key = $value")
}
//打印结果
A = 1000001
B = 1000010
C = 1000011
D = 1000100
E = 1000101
F = 1000110

使用in关键字来检查集合和区间的成员

例如,我想检查5这个数字是否在0,10之间,代码如下:

fun main(args: Array<String>) {
    println(testIn(5))//true
}
fun testIn(i:Int):Boolean{
    //这里in可以取反,!in
    return i in 0..10
}

再举个例子,比如我想检查某个List列表中是否包含某个值,也可以通过in来检查,代码如下:

fun main(args: Array<String>) {
    println(testIn("xiaochao"))//true
}
fun testIn(name: String): Boolean {
    val listdata = ArrayList<String>()
    listdata.add("xiaochao")
    listdata.add("xiaowang")
    listdata.add("laowang")
    return name in listdata
}

Kotlin中的异常

Kotlin中异常与Java中并没有太大区别。但是当Kotlin在使用 try catch?时,却可以将其作为表达式。

fun testException(str:String):Int{
    val number = try{
        Integer.parseInt(str)
    }catch (e:NumberFormatException){
        0
    }
    return number
}

fun main(args: Array<String>) {
        println(testException("55")) //打印结果:55
    println(testException("hello world")) //打印结果:0
}

总结

  1. fun?关键字用来声明函数。val?关键字和 var?关键字分别用来声明只读变量和可变变量。
  2. 字符串模板帮组你避免繁琐的字符串链接。在变量名称前加上 $?前缀或者用 ${ }?包围一个表达式,来把值注入到字符串中。
  3. 熟悉的 if?是带返回值的表达式。
  4. when?表达式类似于Java中的 switch?但功能更强大。
  5. 在检查过变量具有某种类型之后不必显示地转换它的类型:编译器使用智能转换自动帮你完成。
  6. for、while、do-while循环与Java类似,但是for循环现在更加方便,特别是当你需要迭代map的时候,又或是迭代集合需要下标的时候。
  7. 简洁的语法1..5会创建一个区间。区间和数列允许Kotlin在for循环中使用统一的语法和同一套抽象机制,并且还可以使用 in?云算法和 !in?运算符来检查值是否属于某个区间。
  8. Kotlin中的异常处理和Java非常相似,除了Kotlin不要求你声明函数可以抛出的异常(即不需要在函数后显示的 throws Exception)。

原文地址:https://www.cnblogs.com/xxiaochao/p/11497217.html

时间: 2024-11-05 15:36:47

第二章(Kotlin基础)的相关文章

第二章 算法基础 思考题2-1

package chap02; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Random; import org.junit.Test; /*** * 在归并排序中对小数组采用插入排序 * * @author xiaojintao * */ public class ques2_1 { /** * 归并排序算法 * * @param a * @return */ static void m

第二章 算法基础 思考题2-4(逆序对)

1 package chap02; 2 3 import static org.junit.Assert.*; 4 5 import java.util.Arrays; 6 7 import org.junit.Test; 8 9 public class ques2_4 { 10 /** 11 * 逆序对,将一个序列中的所有逆序对打印输出 12 * 13 * @author xiaojintao 14 * 15 */ 16 static void printReverseOrder(int[]

鸟哥的 Linux 私房菜(服务器) 第二章 网络基础概念

鸟哥的 Linux 私房菜(服务器) @(学习笔记)[Linux|Markdown|笔记] [TOC] 第二章 网络基础概念 2.1 网络是个什么玩意儿 OSI 七层协定 分层 负责内容 Layer 1物理层Physical Layer 由于网络媒体只能传送 0 与 1 这种位串,因此物理层必须定义所使用的媒体设备之电压与讯号等, 同时还必须了解数据讯框转成位串的编码方式,最后连接实体媒体并传送/接收位串. Layer 2数据链结层Data-Link Layer 这一层是比较特殊的一个阶层,因为

2016.9.21 鸟哥私房菜服务器篇-第二章网络基础-总结

第二章-网络的基本概念 2.1网络 操作系统很多,比如windows/linux/os X等,这么多的操作系统(不同国家的人)如何进行网络沟通(语言交流)呢? 制定共同的标准.然后在你的系统里提供可以加入该标准的程序代码. 网络是跨平台的. 2.1.1 什么是网络 网络就是几部计算机主机或者网络打印机之类的接口设备,通过网线或者无线网络技术,将这些主机与设备连接起来,使得数据可以通过网络介质(网线或者网卡等硬件)来传输的一种方式. 以太网已经是一项公认的标准接口了,大家可以依据这个标准来开发自己

第二章 impala基础使用

第二章 impala基本使用 1.impala的使用 1.1.impala-shell语法 1.1.1.impala-shell的外部命令参数语法 不需要进入到impala-shell交互命令行当中即可执行的命令参数 impala-shell后面执行的时候可以带很多参数: -h 查看帮助文档 impala-shell -h -r 刷新整个元数据,数据量大的时候,比较消耗服务器性能 impala-shell -r -B 去格式化,查询大量数据可以提高性能 --print_header 去格式化显示

第二章 寄存器基础概念

第二章 寄存器 1.一个典型的CPU由运算器,控制器,寄存器等器件组成. 内部总线实现CPU内部各个器件之间的联系. 外部总线实现CPU和主板上其它器件的联系. 2.8086是Intel系列中16位微处理器,地址总线20位. 8086有14个16位寄存器:AX,BX,CX,DX,是通用寄存器SI,DI,BP,SP,是基址和变址寄存器CS,SS,DS,ES,是段寄存器IP,FLAGS是指令指针和标志寄存器. 3.通用寄存器:一个CPU有多个寄存器,用来存放十六位一般性数据 下面以AX为例 4.汇编

第二章 Python基础知识

第1章 第一个Pyhton程序 Pyhton的两种执行方式:交互式与脚本文件 1.1 交互式 l  交互式模式 直接在Windows或者Linux环境下打开Python解释器执行. 优点:快捷,调试方便. 缺点:不能够保存代码. C:\Users\cc>python3 Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", &quo

第二章 Scorpio-CSharp基础语法介绍 语法篇

1. if 1 var a = 300 3 if (a == 100) { 5 print(100) 7 } else if (a == 200) { 9 print(200) 11 } elif (a == 300) { 13 print(300) 15 } elseif (a == 400) { 17 print(400) 19 } else { 21 print(0) 23 } else if(有空格) 和 elif 和 elseif(无空格)  三种写法都可以使用,都当作 else if

第二章python基础续

2.6基本数据类型--列表 列表的创建 list_test=['张三','李四','alex'] #或 list_test=list('alex') #或 list_test=list(['张三','李四','alex']) 列表的特点和常用操作 特性: 1.可存放多个值 2.按照从左到右的顺序定义列表元素,下标从0开始顺序访问,有序 3.可修改指定索引位置对应的值,可变 常规操作: #索引 >>> l = ['egon','alex','seven','yuan'] >>&

《SQL 基础教程》第二章:查询基础

这一章的结构如下: SELECT 语句基础 算术运算符和比较运算符 逻辑运算符 SELECT 语句可用于查询数据,并且可以设定条件来查询具有特定值的记录.条件的设定就需要算数运算符.比较运算符和逻辑运算符发挥作用. SELECT 语句基础 格式 SELECT <column1>, <column2>, <column3>...FROM <table>; 注意:SELECT 语句后面的对象既可以是列名,也可以是相关的算术表达式. AS 关键字 功能:利用 AS