第一章(入门)
基础
var 可变变量 val 不可变变量
可以不用指定类型,会自动推导 eg:
1
2
3var v1: Int = 10
var v2 = 11
val v3 = 12String 跟 String?是两种不同的类型,String 类型不能为空,String?可以空
强转符号 !! eg:
1
2
3
4
5
6
7
8var s1: String = "123"
var s2: String? = null
fun main(args: Array<String>) {
//需要强转
s1 = s2!!
s2 = s1
}函数声明 fun xxx(param: type): returnType{ … } eg:
1
2
3
4fun printlen(str: String): String {
println("stringValue: $str")
return str
}kotlin中if else 是一个表达式(有返回值),不是语句
1
2
3fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}kotlin中赋值是语句,不是表达式
字符串模版 ->占位符$
1
2
3
4
5//case 1
val str = "kotlin"
println("hello,$str")
//case 2 :表达式
println("hello,${if(str=="kotlin") "kotlin" else "java"}")类定义
Java vs kotlin
1
2
3
4
5
6
7
8
9
10
11public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}转成kotlin: 值对象->只包含数据,不包含对数据的操作
1
class Person(val name: String)
类属性:
- 声明了属性,就隐式声明了该属性的get跟set
- 如果是val属性,那么只有get
- 如果是is开头的属性,get方法也是is开头的
自定义类属性的get跟set方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Rectangle(val height: Int, val width: Int) {
//方式1
val isSquare: Boolean
get() {
return height == width
}
//方式2
val isRect: Boolean
get() = height > 0 && width > 0
}
fun main(args: Array<String>) {
val rectangle = Rectangle(10, 10)
println(rectangle.isRect)
println(rectangle.isSquare)
}
包结构
- kotlin中可以将多个类,多个方法放在一个kt文件中
- 不同包下使用类的时候跟java一致,不同的是kotlin可以导入方法
枚举
java使用enum关键字即可,kotlin需要使用enum class
java
1
2
3public enum Gender {
Man, Woman
}kotlin
1
2
3enum class Gender {
Man, Woman
}
when
When 替代switch case;when跟if else一样是个表达式,不是语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15enum class Gender {
Man, Woman
}
fun getGender(gender: Gender): String {
return when (gender) {
Gender.Man -> "男"
Gender.Woman -> "女"
}
}
fun main(args: Array<String>) {
val gender = getGender(Gender.Man)
println("性别:$gender")
}组合的情况,用逗号隔开
when允许任何对象作为分支条件
when可以不指定参数,分支条件可以为任意的boolean表达式
1
2
3
4
5
6
7
8
9
10fun getLevel(score: Int) =
when {
(score in 0..59) -> "不及格"
(score in 60..100) -> "及格"
else -> throw Exception("分数不正确")
}
fun main(args: Array<String>) {
println(getLevel(10))
}
类的智能转换:java中做类型转换前会使用instanceOf() 方法判断,之后再进行强转,kotlin中使用(a is b)进行判断,并且判断之后a对象自动转换为b类型,不需要强转
while 跟java完全一致
forin替代java中的for循环
整数遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15for (i in 1..10) {
println(i)
}
for (i in 10 downTo 1) {
println(i)
}
for (i in 1..10 step 2) {
println(i)
}
//不包括11
for (i in 1 until 11) {
println(i)
}遍历数组
1
2
3
4val arrayList = arrayListOf<String>("1", "2")
for ((index,item) in arrayList.withIndex()){
println("$index,$item")
}遍历map
1
2
3
4
5
6
7val hashMap = HashMap<String, String>()
hashMap["1"] = "123"
hashMap["2"] = "234"
for ((key,value) in hashMap){
println("$key,$value")
}
in 跟 ! in
- 是否在范围内,范围可以是数字,字符,也可以是实现了Java.lang.comparable接口的类对象实例
- 是否在集合内
1
2
3
4
5
6
7
8
9fun isNumber(c: Char) = c in '0'..'9'
fun main(args: Array<String>) {
println(isNumber('0'))
//string 实现了Java.lang.comparable
println("javascript" in "java".."kotlin")
println("java" !in setOf("java", "kotlin"))
}异常处理
- 跟java 一样用try catch finally
- 它是表达式
- kotlin中函数不需要throws异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14fun readNumber(read: BufferedReader): Int? {
val line = read.readLine()
return try {
Integer.parseInt(line)
} catch (e: Exception) {
null
} finally {
read.close()
}
}
fun main(args: Array<String>) {
print(readNumber(BufferedReader(StringReader("123q"))))
}以上例子中,如果是java,那么需要throws IOException( 因为read.close()方法 ),但是在kotlin中不需要
创建集合
- kotlin没有自己的集合类,跟java公用
- kotlin在java的基础上增加了一些语法糖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21fun main(args: Array<String>) {
val hashSet = hashSetOf(1, 2, 3)
val hashMap = hashMapOf(1 to '1', 2 to '2')
val arrayList = arrayListOf(1, 2, 3)
println(hashSet.javaClass)
println(hashMap.javaClass)
println(arrayList.javaClass)
println(arrayList.last())
println(hashSet.max())
println(hashMap[1])
}
//输出
class java.util.HashSet
class java.util.HashMap
class java.util.ArrayList
3
3
1函数声明时候的默认参数
- 在java的类中会出现大量的方法重载,kotlin的函数参数可以有默认值,这个特性可以减少很多模版化的重载
- kotlin调用方法的时候可以指定参数名称,而且可以不用按方法声明的参数顺序去写,增加了代码易读性。
- 因为java中不具有该特性,java调用该代码的时候必须指定全部参数;@JvmOverloads注解可以让这个方法生成对应的java重载方法,这样就java调用的时候就不用指定全部参数了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun doSomething(
param1: String,
param2: String = "default"
) {
println(param1)
println(param2)
}
fun main(args: Array<String>) {
doSomething("1")
doSomething("1", param2 = "2")
doSomething(param2 = "1", param1 = "2")
}
kotlin跟java可以随便调用吗
kotlin可以直接在.kt文件中写变量写方法等。
Test.kt文件如下
1
2
3
4
5var v1: Int = 10
fun printlen(str: String): String {
println("stringValue: $str")
return str
}java中调用(文件名+Kt是编译之后的class名,getV1跟setV1是编译过程中自动生成的)
1
2
3
4
5//调用方法
TestKt.printlen("111");
//使用变量
TestKt.getV1();
TestKt.setV1(2);
kotlin匿名内部类 ,关键字object+类名{ xxx }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Kt {
//定义匿名内部类
object Inner{
fun sayHello(){
println("hello")
}
}
fun test(){
//kotlin 调用
Inner.sayHello()
}
}
public void test(){
//java调用
Kt.Inner.INSTANCE.sayHello();
}从java的调用方式可以看出来匿名内部类是单例的。
kotlin使用java中Class对象,kotlin中Class是KClass
1
2
3
4
5
6
7
8
9
10
11//J是一个java类
fun test(clazz: Class<J>) {
println(clazz.simpleName)
}
//Kt是一个kotlin类
fun test1(clazz: KClass<Kt>){
println(clazz.simpleName)
}
//调用
test(J::class.java)
test1(Kt::class)in在kotlin中是关键字,如果调用的java常量名字是in需要加
1
J.'in'
新手常见问题
- kotlin中默认的只有基础类型,没有封装类型
- kotlin是空安全的,调用返回值是String的java方法时需要用String?来接受返回值,不能用var。var接受的话会自动推导成String!,如果用var接受,当方法返回值是null的时候,可能会有空安全问题(比如调用.length())。
kotlin中没有静态变量跟静态方法
第二章 函数跟lambda闭包
函数特性
函数参数可以有默认值
如果只有一个语句可以如下
1
fun test() = print("hello")
嵌套函数
函数中可以声明函数
1 | fun test3(){ |
扩展函数
语法
1
2
3
4
5
6
7//扩展java中的File,注意this
fun File.printFileName() = print(this.name)
fun main() {
val file = File("./kotlin_study.iml")
file.printFileName()
}使用场景
- 用于扩展第三方的类
- 用于扩展java的类
- 。。。感觉就是很强大
注意点
- 扩展函数都是静态的(public static final)
- 不具有重载的特性(看上去是对象在调用,实际是类在调用)