Kotlin生成.class放入java编译器
Kotlin 开发效率提高50%
Kotlin 完美兼容java
Kotlin 几乎解决了空指针问题
《第一行代码第三版》Kotlin
(一)变量
val a = 10 // 不可变的a,相当于final
var a = 10 // 可变的a,相当于非final
var a:Int =10 // 指定为Int型,注意I为大写,kotlin里面所有的基本类型都大写了
(二)函数
fun methodName(param1:Int , param2:Int):Int{
return 0
}
语法糖(当函数只有一行的时候可以不用写函数体)
fun methodName(param1:Int , param2:Int):Int = 0
fun methodName(param1:Int , param2:Int) = 0 //还能自动推导
(三)逻辑控制
If 可以有返回值,返回值就是每一个条件中最后一行代码的返回值
fun large(num1:Int,num2:Int)= if(num1>num2) num1 else num2 // 加上语法糖
When 当判断条件很多的时候可以用它; when也还能进行类型匹配用is关键字;when还能不带参数
fun getScore(name:String) = when(name){
"Tom"->86
"Jim"->77
"Jack"->95
else ->0
}
While 和java一样
For 把Java的for-each加强为for-in,没有了for i
0…10双闭区间
0 until 10 左闭右开区间
Step关键字控制步数,step 2 就是I=i+2
10 downTo 1 双闭区间,降序
for(i in 0 until 10 step2){
Println(i)
}
(四)面向对象
类与对象
class Person{}
val p = Person() // 不用写new了
p.name="Jack"
继承
默认所有非抽象类都是不可以被继承的,要用open关键字打开继承
open class Person(){}
class Student : Person(){} //这样子继承
构造函数
->主构造函数
主构造函数没有函数体,直接定义在类名后面即可,如果想要在主构造函数里面写逻辑,要用Init关键字
class Student(val sno: String):Person(){
}
val student = Student("a12") // 必须填上参数
class Student(val sno: String):Person(){
init{
}
}
子类的主构造函数调用父类中的哪一个构造函数,在继承的时候通过括号来指定。
class Student(val sno: String):Person(){}
//表示student类的主构造函数在初始化的时候会调用person类的无参构造函数
->次构造函数
次构造函数用contruct关键字来定义,
一个类既有主构造函数又有次构造函数的时候,次构造函数都必须调用主构造函数
class Student(val sno: String):Person(){
Contruct(): this(""){}
}
//可以只有次构造函数而没有主构造函数
class Student:Person{
Contructor(name:String,age:Int) : super(name,age){}
}
//主构造函数没有,自然就调用父类的主构造函数,注意Person后面没有括号,然后用super
(五)关键字
接口
几乎和java一样,使用的时候用:kotlin也是单继承语言,且后面没有括号,kotlin里面继承和implement统一用冒号
interface Study{
fun readBook()
}
class Student(name:String, age:Int): Person(name,age),Student{ //继承Person,实现Study
Override fun readBook(){}
}
还允许对接口中定义的函数进行默认实现,其实jdk1.8以后也支持这个功能了
interface Study{
fun readBook(){
Println("xxxxx")
}
}
//这样子可以不实现readBook方法,因为会自动调用
可见性修饰符(变化较大)
- Public:表示对所有类都可见,它是默认项。这和java不同
- Private:和java一样,只对当前类可见
- Protected:(java是对当前类、子类和同一包路径下的类可见)它是只对当前和子类可见
- Internal:一些函数只允许在模块内部被调用
数据类和单例类(kotlin特有)
->数据类
在Java中写数据类你需要去重写equals、hashCode、toString方法,而在kotlin里面则这样子使用
data class Cellphone(val brand: String , val price: Double)
// 如果一个类里面没有东西,那么大括号可以省略
->单例类
只需要将class关键字改为object关键字即可,例如
创建:object Singleton{ fun singletonTest(){ println(“”)}}
调用:Singleton.signletonTest()
(六)Lambda编程
List集合
创建1(java和kotlin都能看懂的写法):
val list = ArrayList<String>()
list.add("Apple")
创建2(不可变形式,即只能读):
val list = listOf("Apple","Banana")
for(ele in list){ }
创建3(可变形式):
val list = mutableListOf("Apple","Banana")
list.add("Orange")
Set集合
和List差不多就变成了SetOf、mutableSetOf,无序的
Map集合
创建1(java和kotlin都能看懂的写法):
val map = HashMap<String,Int>()
Map.put("Apple",1)
Map.get("Apple")
创建2(可变形式):
val map = mutableMapOf("Apple" to 1, "Banana" to 2)
Map["Orange"] =3
for((fruit,number) in map){
println(fruit+":"+number)
}
集合的函数式API
Lambda表达的基本语法:
{参数名字1:类型 , 参数名字2:类型 -> 函数体}
找到集合中单词最长的那个水果?
val list = listOf(“Apple”,”Banana”,”Orange”)
var maxlen = list.maxBy{ it.length }
// 最简版本,maxBy函数用来把根据传入参数为条件找到最大值
我们从最复杂的基本版写起来:
var lambda = { fruit:String -> fruit.length}
var maxlen = list.maxBy{ lambda }
我们可以直接把Lambda表达式传入进去:
var maxlen = list.maxBy({ fruit: String -> fruit.length })
当lambda参数是函数的最后一个参数时,可以把它移到外面去:
var maxlen = list.maxBy() { fruit: String -> fruit.length }
当lambda参数时函数的唯一参数时,可以把括号省略:
var maxlen = list.maxBy { fruit: String -> fruit.length }
由于有出色的类型推导机制,因此一般情况下参数列表不用标明类型:
var maxlen = list.maxBy { fruit -> fruit.length }
当lambda表达式中的参数只有一个时,不必声明参数名字,而是使用it关键字来代替:
var maxlen = list.maxBy { it.length }
集合中几个常用的函数式API
Map函数:用来将集合中的每个元素都映射成另外的值
val list = listOf("Apple", "Banana", "Orange", "Orange_Juice")
val mUpperName = list.map { it.toUpperCase() } // 全部映射为大写单词
filter函数:用来过滤集合中的数据
val list = listOf("Apple", "Banana", "Orange", "Orange_Juice")
val res = list.filter { it.length > 5 }
.map { it.toUpperCase() }
// 找到长度大于5的所有元素,并把他们全部转化为大写
Any函数:判断集合中是否至少存在一个元素满足指定条件
val list = listOf("Apple", "Banana", "Orange", "Orange_Juice")
val anyResult = list.any { it.length <= 5 } // true
All函数:判断集合中是否所有元素都满足条件
val list = listOf("Apple", "Banana", "Orange", "Orange_Juice")
val allResult = list.all { it.length <= 5 } // false
Kotlin调用java方法时也可以用函数式API
如果我们在Kotlin代码中调用了一个java方法,并且该方法是一个接口且只有一个待实现方法,那么就可以使用函数式API
新建一个Thread怎么写?
//创建匿名类实例的时候用object关键字代替New
Thread(object : Runnable {
override fun run() {
TODO("Not yet implemented")
}
}).start()
//不显示重写run方法,Kotlin也能明白后面的Lambda表达式的作用
Thread(Runnable {
TODO()
}).start()
//如果一个java方法的参数列表中不存在一个以上java单抽象方法接口参数,那么对接口名可以省略
Thread({
TODO()
}).start()
//最后可以省略成这样子去写
Thread {
TODO()
}.start()
Click点击事件怎么去写?
mytext.setOnClickListener {
Toast.makeText(this, "我是一个文本", Toast.LENGTH_SHORT).show()
}
(七)空指针检测
Kotlin利用编译时判空检查的机制几乎杜绝了空指针异常。
1)Kotlin默认所有的参数和变量都不可为空,如果向函数里面传入一个空的参数,就会报错
2)我们可以在参数中写可空类型(例如Study?、String?、Int?),但是要在代码里面进行空指针异常处理,例如进行判断
fun test(str: String?) {
if (str != null) {
TODO()
}
}
判空辅助工具
1 )?.操作符:不为空就执行.后面的方法【取代if判空】
Str?.todoSomething()
2)?:操作符:不为空返回左边,为空返回右边【取代if else 判空】
fun getTextLength(str: String?): Int {
return str?.length ?: 0
}
3)let函数:将原始调用对象作为参数传递到lambda表达式中(obj和obj2是同一个对象)
Obj.let{
Obj2 ->
//编写具体的逻辑
}
fun doStudy(study : Study?){
Study?.let{Stu ->
Stu.readBook()
Stu.doHomework()
}
}
//代码还可以简化成如下
fun doStudy(study :Study?){
Study?.let{
it.readBook()
it.doHomework()
}
}
(八)Kotlin中的小魔术
字符串内嵌表达式
不需要像使用java时那样傻傻地拼接字符串了,而是可以直接将表达式写在字符串里面
val bandName = "Samsung"
val price = 12999
println("CellPhone(brand=$bandName,price=$price)")
函数的参数默认值
在Kotlin中完全可以通过只编写一个主构造函数,然后通过给参数设定默认值的方式来实现次构造函数
//给第一个参数设置默认值,这样在调用函数时,
//可以选择给第一个参数传参,也可以选择不给第一个参数传参数
fun printParam(num: Int = 100, str: String) {
println("num is $num,str is $str")
}
//这时候想要让num使用默认值怎么办?
//Kotlin提供了一种机制,可以使用键值对的方式进行传参
printParam(str = "world")