准确来说,Java是解释性语言,Kotlin能被编译为class文件,再在虚拟机中运行

Kotlin几乎杜绝了空指针异常

运行Kotlin代码:IDEA创建Kotlin项目;在线运行kotlin代码;Android Studio创建一个main()函数

fun main() {println("Hello, world!!!")
}

2.3.1变量

Kotlin中定义一个变量,只允许valvar进行声明。

valvalue的简写)声明不可变的变量,对应Java中的final变量,不可二次赋值(地址)

varvariable的简写)用来声明一个可变的变量,对应Java中的非final变量。

Kotlin拥有出色的类型推导机制

var a=10       //整型
var b="hello"  //字符串

代码结尾不加分号

val a: Int = 10  //显示声明变量a为Int类

Kotlin中完全摒弃基本数据类型,全部使用对象数据类型

全部使用对象数据类型

全部使用对象数据类型

全部使用对象数据类型

Number是Kotlin内置抽象类,是Int、Long、Float、Double的父类

Java与Kotlin数据类型对照表

永远优先使用val来声明一个变量,而当val没有办法满足你的需求时再使用var。这样设计出来的程序会更加健壮,也更加符合高质量的编码规范

2.3.2 函数

函数==方法

main()函数是程序的入口函数

//入口函数
fun main() {println("Hello, world!!!")
}//自定义函数
fun methodName(param1: Int,param2: Int):Int{return 0
}

fun:定义函数的关键字

参数格式: 参数名称:类型 paramName:Int

返回值类型:在参数括号后,不写则默认为void

import kotlin.math.max
fun main() {val a = 30val b = 43val value = largerNumber(a,b)println("larger number is "+value)
}
​
fun largerNumber(num1: Int,num2: Int):Int{return max(num1,num2)
}

语法糖:若函数中只有一行代码,Kotlin允许直接将该行代码写在函数定义尾部,并用等号连接。

= 表达了 return

//                                      = 表达 return
fun largerNumber(num1:Int,num2:Int):Int = max(num1,num2)

继续简化,让Kotlin自动推导返回类型

fun largerNumber(num1:Int,num2:Int) = max(num1,num2)

2.4 程序逻辑控制

顺序语句

条件语句:if 和 when

循环语句:

2.4.1 if条件语句

与Java相同的用法;略

if有返回值:

//每个条件的最后一行代码作为返回值
fun largerNumber(num1:Int,num2:Int):Int{val value = if(num1>num2){num1}else{num2}return value
}
//简化,直接返回
fun largerNumber(num1:Int,num2:Int):Int{return if(num1>num2){num1}else{num2}
}
//仅一行代码,继续简化
fun largerNumber(num1:Int,num2:Int) = if(num1>num2){num1
}else{num2
}

继续简化

fun largerNumber(num1:Int,num2:Int)=if(num1>num2) num1 else num2

2.4.2 when条件语句

when是为解决switch的痛点,并增加许多强大的新特性

when也有返回值

//精准匹配
when(param){
​匹配值 -> { 执行逻辑 }"Tom" -> 10  //当参数值为Tom时返回10
}
​
//类型匹配    is相当于Java中instanceOf关键字
when(param){is Int -> {}is Double -> {}else -> {}
}//简化 前
fun getScore(name:String)=if(name == "Tom"){86
} else if(name =="Jim"){77
}else if(name == "Jack"){95
}else if(name == "Lily"){100
}else{0
}
//使用when简化
fun getScore(name:String) = when(name){"Tom" -> 86"Jim" -> 77"Jack" -> 95"Lily" -> 100else -> 0
}
fun checkNumber(num:Number){//类型匹配when(num){is Int -> println("number is Int")is Double -> println("number is Double")else -> println("number not support")}
}
//无参数的when语句
fun getScore(name:String) = when{//将条件表达式写在匹配值的位置,可对参数做一定的操作name.startsWith("Tom") -> 86name == "Jim" -> 77name == "Jack" -> 95name == "Lily" -> 100else -> 0
}

2.4.3 循环语句

while循环与Java一样

for循环不同

for-in循环

声明一个闭区间

val range = 0..10  //创建[0,10]的区间  闭区间
fun main() {//使用 for-in 循环遍历区间for(i in 0..10){println(i)}
}

开区间

val range = 0 until 10  //创建[0,10)的区间

step:设置步长,每次加几

fun main(){for(i in 0 until 10 step 2){println(i)}
}

..until 创建升序区间

降序区间downTo

fun main(){for(i in 10 downTo 1){println(i)}
}

2.5.1 类与对象

创建类Person:

class Person{var name = ""var age = ""fun eat(){println(name + " is eating. He is " + age +"years old.")}
}

实例化类:与Java的区别,去掉了new

val p = Person()  //表示调用了该类的构造函数
fun main(){val p = Person()p.name = "Jack"    // 为Person的实例化对象赋值p.age = 19p.eat()            // 调用方法
}

2.5.2 继承与构造函数

Effective Java这本书中明确提到,如果一个类不是专门为继承而设计的,那么就应该主动将它加上final声明,禁止它可以被继承。

继承

新建Student类

class Student{var sno = ""var grade = 0
}

要让Student类继承Person类,需要做两件事:

1.使Person类可以被继承

在kotlin中任何一个非抽象类默认不可被继承,相当于Java中给类加final

open关键字:在class之前加

open class Person{}

2.继承:使用:

class Student : Person() {var sno = ""var grade = 0
}

()表示调用了构造函数

Kotlin中构造函数

主构造函数 和 次构造函数

主构造函数

默认都有一个不带参数的主构造函数,可显示指明参数,它没有函数体,直接定义在类名后

//         sno与grade字段在被初始化后不可变,故直接设置为val
//         主构造函数   将字段都放入其中
class Student(val sno: String, val grade:Int) : Person(){}

在实例化以上类时,必须传入构造函数中所有的参数

val student = Student("wu",59)   

构造函数中的参数创建实例时传入的,不需要重新赋值,因此我们可以将参数全部声明为val

主构造函数无函数体,若想在主构造函数中编写一些逻辑,可写在init结构体中

class Student(val sno: String, val grade: Int) : Person(){init{println("sno is "+sno)println("grade is "+grade)}
}

继承规定:子类 中的构造函数必须调用 父类 中的构造函数

如何体现调用了呢?括号()

改造Person为有参构造函数

open class Person(val name: String, val age: Int){...
}

改造Student类

// 将父类的name,age属性作为参数,但不需要指定var或val
class Student(val sno: String, val grade: Int,name: String,age: Int) : Person(name,age){init{println("sno is "+sno)println("grade is "+grade)}
}

不能再将父类中的字段声明为val,因为在父类已经指定了。

次构造函数

一个类只能有一个主构造函数,但可以有多个次构造函数

次构造函数与主构造函数的区别:有函数体

Kotlin规定:一个类有主又有次,所有次必须调用主(包括间接调用:调用调用主的次构造函数)

次构造函数通过constructor关键词定义

这里定义两个次构造函数:

第一个接收name和age参数,通过this关键字调用主构造函数,并为主构造函数赋值

第二个不接收任何参数,通过this调用另一个次构造函数

class Student(  val sno: String,val grade: Int, name: String,age: Int) :Person(name,age){constructor(name:String, age:Int):this("",0,name,age){}constructor(): this("",0){}
}

无主构造函数,仅有次构造函数,委派隐式发生,并执行块

class Person(val pets: MutableList<Pet>=mutableListOf())
​
class Pet{constructor(owner: Person){owner.pets.add(this)}
}
若类具有主构造函数,则次构造函数,则次构造函数中必须调用主构造,间接或直接

使用this()来调用主构造

即使类没有主构造函数,委派仍然隐式发生,并且仍然执行初始值设定项块:

class Constructors {init {println("Init block")}
​constructor(i: Int) {println("Constructor $i")}
}

且这个生成的 主构造函数的可见性 是公开的

若不希望它是公共的,就需要声明可见性

class DontCreateMe private constructor(){ }

2.5.3 接口

单继承,多实现

继承与实现都使用 : 来实现

接口后无()

实现接口就必须实现接口中所有抽象方法

支持多态

支持多个默认方法

函数的可见性修饰符

Kotlin中有4种,定义在fun前

public

所有类可见,在Kotlin中属于默认项

private

与Java一致,只在本类中可以访问

protected

在Kotlin中表示对当前类和子类可见

internal

只对同一模块内的类可见

2.5.4 数据类(实体类POJO)与单例类

数据类

在Java中一个实体类中,需要有构造方法,get/set方法,hashCode(),toString等

在Kotlin中只需一行代码 data

data class Cellphone(val brand: String, val price: Double)

只需在类之前加data,Kotlin会根据主构造函数中参数自动生成equals(),hashCode(),toString()等方法,减少开发工作量

在使用==比较两个对象时,会自动调用equals(),data根据参数来比较,若参数相同则true

单例类

在Kotlin中,只需将class关键字改为object关键字即可

object Singleton{}
object Singleton{fun singletonTest(){println("singletonTest is called.")}
}
//调用方式
Singleton.singletonTest()

2.6 Lambda编程

2.6.1 集合的创建与遍历

List,Set

ArrayList,LinkedList

HashSet

HashMap

val list = ArrayList<String>()
list.add("Apple")
list.add("Banana")
list.add("Orange")
list.add("Pear")
//简化写,相当于Java中Arrays.asList();
val list = listOf("Apple","Banana","Orange","Pear")

List集合

//遍历集合
fun main(){val list = listOf("Apple","Banana","Orange","Pear")for(fruit in list){println(fruit)}
}

listOf()与Java中一样,也是不可变的集合,不能添加、修改或删除

可变集合

使用mutableListOf()

fun main(){val list = mutableListOf("Apple","Banana","Orange","Pear")list.add("Watermelon")for(fruit in list){println(fruit)}
}

Set集合

自动去重

val set = setOf("Apple","Banana","Orange","Pear")
​
for(fruit in set){println(fruit)
}

Map集合

HashMap

//类似Java写法
val map = HashMap<String,Int>()
map.put("Apple" ,1)
map.put("Banana", 2)

Kotlin中不建议使用put()和get()方法对Map进行加和读

推荐使用数组下标语法结构

map["Apple"] = 1

读取

val number = map["Apple"]

简便写法:mapOf(),mutableMapOf()

val map = mapOf("Apple" to 1,"Banana" to 2,"Orange" to 3,"Pear" to 4)

to不是关键字,而是infix函数

遍历Map集合

fun main(){val map = mapOf("Apple" to 1,"Banana" to 2,"Orange" to 3,"Pear" to 4)for((fruit, number) in map){println("fruit is " + fruit +", number is "+ number)}
}

2.6.2 集合的函数式API

maxBy

1.找出水果集合中单词最长的水果

val list = listOf("Apple","Banana","Orange","Pear")
val maxLengthFruit = list.maxBy {  it.length  }
println("max length fruit is " + maxLengthFruit)

不建议在Lambda表达式中编写太长的代码

Lambda表达式的语法结构:

{ 参数名1: 参数类型, 参数名2: 参数类型 ->函数体 }

参数列表结尾的->,表示函数体的开始

函数体中可以写任意行代码,最后一行代码会自动作为 返回值

由繁入简

maxBy:普通函数,接收一个Lambda类型的参数,

在遍历时将遍历的值作为参数传递给Lambda表达式。

工作原理:以传入的内容为条件并最大化的要求来遍历集合,

传入length则条件自然就是单词长度

//原始写法:
val list = listOf("Apple","Banana","Orange","Pear")
//规则 { 参数名1: 参数类型 ->函数体 }
val lambda = { fruit: String -> fruit.length }
val maxLengthFruit = list.maxBy(lambda)

不用lambda参数

val maxLengthFruit = list.maxBy({fruit: String -> fruit.length})

Kotlin规定:当Lambda参数是函数最后一个参数时,可将Lambda表达式移到函数括号外

val maxLengthFruit = list.maxBy() { fruit: String -> fruit.length }

根据类型推导,进一步简化

val maxLengthFruit = list.maxBy{ fruit -> fruit.length }

当Lambda表达式的参数列表只有一个参数,不必声明参数名,用it关键字代替

val maxLengthFruit = list.maxBy { it.length }

map

//将所有水果名变大写
val newList = list.map{ it.toUpperCase() }

filter

过滤集合中的数据,可结合其他函数一起使用

//先保留5个字母以内的水果,留下的单词 变大写
//先过滤再变大写效率高,反过来就低一点
val newList = list.filter{ it.length <= 5 }
                  .map{ it.toUpperCase() }

any,all

any:是否存在

all:是否所有都

2.6.3 Java函数式API的使用

如果在Kotlin中调用Java方法,该方法接收了一个Java单抽象方法接口参数,就能使用函数式API

单抽象方法接口:Runnable接口

new Thread(new Runnable(){@Overridepublic void run(){System.out.println("Thread is running");}
}).start();

翻译为kotlin

//创建匿名类用object关键字
Thread(object : Runnable{override fun run(){println("Thread is running")}
}).start()

使用Lambda表达式规则化简

Thread(Runnable{println("Thread is running")
}).start()

若参数列表仅有一个Java单抽象方法接口参数

Thread({println("Thread is running")
}).start()

Lambda表达式是方法最后一个参数,移到方法括号外,

唯一一个参数,省略括号Thread()

Thread{println("Thread is running")
}.start()
button.setOnClickListener{}

2.7 空指针检查

Kotlin默认参数和变量都不可以为空,若为空,编译出错

若业务逻辑需要个空,则需要可为空的类型系统

2.7.1 可为空的类型系统

在类名后加上问号

Int? 表示 可为空整型

String? 表示 可为空字符串

却依然编译不通过,

还需要处理掉空指针异常

判空

fun doStudy(study: Study?){//这样就是处理了if(study != null){study.xx()study.xx()}
}

2.7.2 判空辅助工具

?.操作符

当对象不为空时正常调用,为空什么都不做

if(a!=null){a.doSomething()
}
​
等价于
||
||
a?.doSomething()
fun doStudy(study: Study?){//这样就是处理了study?.xx()study?.xx()
​
}

?:操作符

左右都接收一个表达式,左不为空则返回左边,否则返回右边

val c = a ?: b
val c = if(a != null){a
} else {b
}

操作符混用

//                 text可能为空    不为空调用length。否则啥也不做
fun getTextLength(text: String?) = text?.length ?: 0//不为空返回length。否则返回0

若已经进行了非空判断,仍编译失败,如在方法外判断非空,而方法内不知道,编译不通过

非空断言

在对象后面加!!

表示我确信这个对象不会为空,不需要你再来做空指针检查了。

var content: String? = "hello"
​
fun main(){if(content != null){printUpperCase()}
}
​
fun printUpperCase(){val upperCase = content!!.uppercase()   // !! 尽量少用println(upperCase)
}

let函数

函数式API编程接口,会将调用对象作为参数传递到表达式中

obj.let{obj2 ->//编写具体业务逻辑
}

obj与obj2实际上是同一个对象

实例:

var study: Study?=null
​
fun doStudy(study: Study?){//有点啰嗦,两次判断同一个对象是否为空study?.xx()study?.xx()
​
}
fun doStudy(study: Study?){study?.let{stu ->stu.XX()stu.XX()}
}
//继续简化
fun doStudy(study: Study?){study?.let{it.xx()it.xx()}
}

2.8 Kotlin中的小魔术

2.8.1 字符串内嵌表达式

将表达式写在字符串中

${}

仅有一个变量时,大括号省略

val brand = "Samsung"
val price = 1299.99
​
println("Cellphone(brand="+brand+", price="+price+")")
​
//化简
println("Cellphone(brand=$brand, price=$price)")

2.8.2 函数的参数默认值

通过给函数的参数设定默认值,一定程度上替代次构造函数的功能

//                             设置了默认值,实例化时可传可不传
fun printParams(num: Int, str: String = "hello"){println("num is $num, str is $str")
}
​
fun main(){printParams(123)}
//            存在顺序问题
fun printParams(num: Int = 100, str: String){println("num is $num, str is $str")
}
​
//通过键值对传参
fun main(){printParams(str="hello")printParams(str="hello",num=123)
}

2.9 小结

变量、函数、逻辑控制语句、面向对象编程、Lambda编程、空指针检查机制...

第一行代码读书笔记(Chapter2 探究新语言,快速入门Kotlin编程)相关推荐

  1. 第一行代码读书笔记1+常见错误分析

    1.eclipse里面的视图在 windows ---- show views ---- other ----- Android 2.需要掌握Logcat的使用 Logcat是你在茫茫人海中寻找到一片 ...

  2. 日报2015/11/11(第一行代码读书笔记)

    SQLite数据存储 这里需要说明的是,要使用这种存储,在开发的时候最好是使用模拟器或者把真机root,不然没有权限访问数据库所在的位置.po主直接把三星的s4用刷机大师刷成了别的系统,顺便root掉 ...

  3. 第一行代码读书笔记3+错误分析

    as中怎么删除项目 file---project structure 然后点击左边的 + 与 - 进行删除. 参考资料:http://jingyan.baidu.com/article/c74d600 ...

  4. 日报2015/11/17(第一行代码读书笔记)

    ContentResolver 使用内容提供器是Android实现跨程序共享数据的标准方式. 基本用法 这里要访问的是通讯录,里面已经有一个系统自己的ContentProvider 数据查询无非是要最 ...

  5. 从零开始写安卓APP 《第一行代码》笔记 第一周

    这是软件开发课的任务,本人其实不会java也不会安卓开发.以前只做过web端,因为某课程的爆炸实验单人撸了全栈.不过好在很早前就想学了,这里记录一下过程.放的主要是<第一行代码>的一些笔记 ...

  6. 第一行代码阅读笔记---基本知识

    在res中,我们会看到很多目录,分别如下: drawable-hdpi drawable-ldpi drawable-mdpi drawable-xxhdpi layout menu values v ...

  7. 第一行代码学习笔记第六章——详解持久化技术

    知识点目录 6.1 持久化技术简介 6.2 文件存储 * 6.2.1 将数据存储到文件中 * 6.2.2 从文件中读取数据 6.3 SharedPreferences存储 * 6.3.1 将数据存储到 ...

  8. 第一行代码学习笔记第七章——探究内容提供器

    知识点目录 7.1 内容提供器简介 7.2 运行权限 * 7.2.1 Android权限机制详解 * 7.2.2 在程序运行时申请权限 7.3 访问其他程序中的数据 * 7.3.1 ContentRe ...

  9. 第一行代码学习笔记第二章——探究活动

    知识点目录 2.1 活动是什么 2.2 活动的基本用法 2.2.1 手动创建活动 2.2.2 创建和加载布局 2.2.3 在AndroidManifest文件中注册 2.2.4 在活动中使用Toast ...

最新文章

  1. vue.js 发布后路径引用问题
  2. android 增删改查 源码_学生信息增删改查小程序案例(springboot服务端)
  3. Prim算法 求出 最小生成树
  4. php7 方法,PHP7中方法的弃用
  5. SharePoint2010内容类型剖析(四)
  6. 沼跃鱼早已看穿了一切 C/C++
  7. EasyUI的DataGrid 分页栏英文改中文解决方案
  8. 【论文写作】毕业论文怎么写?写作步骤是什么?
  9. Spring.Net配置多数据源
  10. Struts2学习日记(二)简单的Struts2登陆实现(Action继承ActionSupport类)
  11. cakephp2.X教程第一部分(基于cakephp1.3.4在线教程的改编)
  12. java电力巡检系统 项目讲解_苏河湾1号街坊项目电力监控系统的设计与应用
  13. 网易云音乐数仓模型设计实践
  14. c语言printf()输出格式大全(转载)
  15. 泰山OFFICE技术讲座:介绍几个看着相似的标点
  16. Unhandled Exception:System.DllNotFoundException: Unable to load DLLquot;**quot;:找不到指定的模块
  17. 数据仓库知识与实战——电信运营商数仓建模
  18. 99. 激光炸弹(前缀和)
  19. 基于16S的细菌群落功能预测工具Tax4Fun2
  20. 云计算工程师必备的10本书

热门文章

  1. 儿童在未来游戏中的监管与保护趋势
  2. 移动广告业务发展现状分析
  3. JECloud快速入门手册_【数据字典】
  4. mysql导入sas文件夹_SAS建立本地文件夹
  5. 一世英雄一世尘 - 读《金庸传》
  6. React入门(一)之基本语法(内容较多)
  7. 当房地产插上数字翅膀后,成本收益几何?|2021中国房地产数字峰会
  8. 比特大陆面临破产,吴忌寒:兄弟,把你简历寄过来
  9. 【转载】一句话实现五彩LINUX
  10. 微信公众号流量入口-搜索排名