Kotlin学习网站:
Android 开发者 | Android Developers
Kotlin Programming Language
Kotlin语法
Kotlin基础语法
1. var和val
var 定义可变变量
val 定义不可变变量 优先使用
2. 类型推导
编译器可以在不显式声明类型的情况下,自动推导出它所需要的类型。
var infoStr = "AAA" // 相当于 var infoStr : String = “AAA”
var infoChar = 'A' // 相当于 var infoChar : Char = 'A'
var infoInt = 99 // 相当于 var infoInt : Int = 99;
Kotlin 是一种静态语言,在编译期就确定了是什么类型的变量,后续就没有办法再更改变量的类型。
3. 函数
// Unit == Void
fun main():Unit{
add(1,2)
}
// 返回值类型放在函数名后 代码块式函数体
fun add(num1:Int,num2 : Int) : Int{
return num1 + num2
}
// 返回类型 经过类型推导 : Int 表达式函数体
fun add1(num1:Int,num2 : Int) = num1 + num2
// 返回类型 类型推导 : String
fun add2() = "AAA"
// 可变参数 使用vararg关键字
fun lenMethod(vararg value : Int){
}
lambda表达式函数
val addMethod : (Int , Int) -> = {num1,num2 -> num1 + num2}
// 使用
fun main():Unit{
val r = addMethod(1,2)
}
4. 字符串模板
fun main(){
val age = 28
val name = "AAA"
val sex = 'M'
println("name : $name, age : $age, sex : $sex")
// 换行
val infoMessage = """
AAAA
BBBB
CCCC
DDDD
EEEE
""".trimIndent()
println(infoMessage)
// 打印$符号
val price = """
${"$"}99999
""".trimIndent()
}
5. NULL检查机制
使用"?"判断是否为null
var info : String? = null;
println(info?.length) // 如果为null ?之后的不执行
// :Int? 允许返回null
fun testMethod():Int?{
return null
}
6. 区间
“in” 关键字
for(i in 1..9){
}
// 从大到小
for(i in 9 downTo 1){
}
// 跳2步执行
for(i in 1..9 step 2){
}
// 排除最后一个元素
for(i in 1 until 10){
}
7. 比较
== 比较值本身
=== 比较对象地址
val name1 :String = "张三"
val name2 : String = "张三"
// 比较值本身
println(name1.equals(name2))
println(name1 == name2)
// 比较对象地址
println(name1 === name2)
8.数组
val number :Array<Int> = arrayOf(1,2,3,4,5,6,7,8,9)
println(number[0])
println(number[1])
for (num : Int in number){
println(num)
}
// {value : Int -> (value + 200)} 定义一个Int类型的value 输出value + 200
val number2 : Array<Int> = Array(10,{value : Int -> (value + 200)})
for (value : Int in number2){
println(value)
}
9. 条件判断
if和when
if:
val num1 :Int = 999
val num2 : Int = 888
val maxValue : Int = if(num1 > num2) num1 else num2
println(maxValue)
val max : Int = if(num1 > num2 ){
println()
num1
}else{
println()
num2
}
println(max)
when:
val number = 5
when(number){
1 -> println("一")
2 -> println("一")
3 -> println("一")
4 -> println("一")
5 -> println("一")
else -> println("其他")
}
// Any 相当于 Java中的Objcet
val number1 = 100
val result : Any = when(number1){
in 1..100 -> {
println("1..100")
"200"
}
in 101..500 ->{
println("101..500")
true
}
else -> {
println("其他")
99 // 返回值 判断返回类型
}
}
println(result)
10. 类和对象
类
// class Person(id:Int) 这样写 是 public final class Person 是无法继承的
// 要想继承 需要在前面加上open
open class Person(id:Int) // 主构造函数
{
// 次构造函数 必须引用主构造函数
constructor(id:Int,name:String):this(id){}
// 次构造函数
constructor(id: Int,sex:Char):this(id){}
// 次构造函数
constructor():this(1234){}
}
// Student 继承 Person
class Student(id:Int) : Person(id) {
// 在kotlin中,所有的变量没有默认值 所以要使用就必须先给出默认值 这一点与Java有区别
// 使用lateinit懒加载 可以先不加载 等到要使用的时候再加载 要使用的时候必须赋值
lateinit var name :String
var age:Int = 0;
}
11. 抽象类和接口
// 接口
interface CallBack {
fun testMethod():Boolean
}
// 抽象类 abstract 有 open的作用
abstract class Person() : CallBack
{
abstract fun test1():Int
abstract fun test2()
}
class Student() : Person() {
override fun test1(): Int {
TODO("Not yet implemented")
}
override fun test2() {
TODO("Not yet implemented")
}
override fun testMethod(): Boolean {
TODO("Not yet implemented")
}
}
12 data数据类
相当于Java中的JavaBean
// data 数据类 相当于 Java中的JavaBean 查看自动生成的Java代码 Tool-> kotlin -> show kotlin Bytecode
data class Person2(val id:Int,val name:String,val sex:Char)
自动生成的Java代码
public final class Person2 {
private final int id;
@NotNull
private final String name;
private final char sex;
public final int getId() {
return this.id;
}
@NotNull
public final String getName() {
return this.name;
}
public final char getSex() {
return this.sex;
}
public Person2(int id, @NotNull String name, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.id = id;
this.name = name;
this.sex = sex;
}
public final int component1() {
return this.id;
}
@NotNull
public final String component2() {
return this.name;
}
public final char component3() {
return this.sex;
}
@NotNull
public final Person2 copy(int id, @NotNull String name, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person2(id, name, sex);
}
// $FF: synthetic method
public static Person2 copy$default(Person2 var0, int var1, String var2, char var3, int var4, Object var5) {
if ((var4 & 1) != 0) {
var1 = var0.id;
}
if ((var4 & 2) != 0) {
var2 = var0.name;
}
if ((var4 & 4) != 0) {
var3 = var0.sex;
}
return var0.copy(var1, var2, var3);
}
@NotNull
public String toString() {
return "Person2(id=" + this.id + ", name=" + this.name + ", sex=" + this.sex + ")";
}
public int hashCode() {
int var10000 = Integer.hashCode(this.id) * 31;
String var10001 = this.name;
return (var10000 + (var10001 != null ? var10001.hashCode() : 0)) * 31 + Character.hashCode(this.sex);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person2) {
Person2 var2 = (Person2)var1;
if (this.id == var2.id && Intrinsics.areEqual(this.name, var2.name) && this.sex == var2.sex) {
return true;
}
}
return false;
} else {
return true;
}
}
}
自动生成了set、get,equals、hashCode、toString、copy等方法
12. 单例
// Object修饰的类 就是单例的 只会实例化一次
object Obj {
}
单例的第一种写法:
class Manager {
object Holder{
var instance = Manager()
}
// 派生操作 相当于Java中的static
companion object{
fun getInstance() : Manager = Holder.instance
}
// 方法
fun show(name:String){
println("show:$name")
}
}
// 调用
fun main(){
val manager = Manager.getInstance()
manager.show("KimLiu")
}
单例的第二种写法:
class Manager2 {
companion object{
private var instance : Manager2? = null // 可以为null
fun getInstance() : Manager2?{
if (instance == null){
instance = Manager2();
}
return instance
// 另外一种写法 自己负责instance为null的情况,确保instance不为null
return instance!!
}
}
// 方法
fun show(name:String){
println("show:$name")
}
}
fun main(){
val manager : Manager2? = Manager2.getInstance()
manager?.show("KimLiu")
}
13.内部类
使用inner关键字
class Test {
// 加了inner 是内部类 不加inner是嵌套类
inner class innerClass{
}
}
Kotlin高级
1. Kotlin和Java相互调用
1.1 Java调用Kotlin代码
Kotlin代码:
class MyUtils {
fun show(info: String) {
println(info)
}
}
// MyUtils.kt 写了一个show MyUtilsKt
fun show(info: String) {
println(info)
}
Java代码:
public class Client {
public static void main(String[] args) {
// 这个show方法是kotlin方法 使用Java调用Kotlin方法时,会自动生成MyUtilsKt类
MyUtilsKt.show("Derry1");
// MyUtils类里面的方法
new MyUtils().show("new Derry2");
}
}
1.2 Kotlin调用Java代码
Kotlin代码:
class ClientKT {
}
fun main(){
// in在KT中是关键字 在KT中使用`in` 解决冲突
StudentJava.`in`
// 在KT中调用Java代码 返回值是String! 因为有!所以要用一个变量接收 有可能为空
var str:String? = StudentJava().string
str?.length
// 在KT中传入Java Class 需要使用 StudentJava::class.java
showClass(StudentJava::class.java)
// 在KT中传入KT Class 使用StudentKT::class
showClass2(StudentKT::class)
}
fun showClass(clazz:Class<StudentJava>){
}
fun showClass2(clazz:KClass<StudentKT>){
}
Kotlin调用Java的回调 Java的CallBack
public interface JavaCallBack {
void show(String info);
}
public class JavaManager {
public void setCallBack(JavaCallBack javaCallBack){
javaCallBack.show("===");
}
}
kotlin调用Java的回调
JavaManager().setCallBack(JavaCallBack {
print(it)
// TODO
})
JavaManager().setCallBack(object :JavaCallBack{
override fun show(info: String?) {
TODO("Not yet implemented")
}
})
JavaManager().setCallBack { TODO("Not yet implemented") }
val callback2 = JavaCallBack { info -> println(info) }
JavaManager().setCallBack(callback2)
Kotlin调用Kotlin的回调
KTManager().setCallBack(object:KTCallBack{
override fun show(info: String) {
TODO("Not yet implemented")
}
})
val callBack3 = object : KTCallBack{
override fun show(info: String) {
TODO("Not yet implemented")
}
}
KTManager().setCallBack(callBack3)
2. Kotlin代码和Java代码隔离
Kotlin中,支持使用特殊符号给函数命名,只要Java不认识Kotlin的函数名,就无法调用Kotlin的函数
`showTest`();
`4325436465375`("Derry");
` `('M');
3. 解构声明
有时把一个对象解构成很多变量会很方便,例如:val (name, age) = person,这种语法称为 解构声明 。
在声明数据类的时候,会自动生成componentN()方法,对应按声明顺序出现的所有属性,如name就是component1(),age就是component2(),而解构声明的val (dName, dAge)事实上就是调用component1()和component2()方法。
写一个例子:
class Student(var id: Int,var age:Int,var name : String)
{
// 解构
operator fun component1() : Int = id
operator fun component2(): Int = age
operator fun component3(): String = name
operator fun component4(): String = "-----"
}
fun main(){
val stu = Student(1111,222,"Name")
val(n1,n2,n3,n4) = stu
println("n1 : $n1,n2 : $n2,n3 : $n3,n4 : $n4")
}
Kotlin高阶函数
高阶函数: 接收另一个函数(函数类型)作为参数,或返回值的类型是另一个函数。
1. 认识第一个高阶函数
fun main(){
show(true){
'S'
}
show(false){
'F'
}
}
/**
* 高阶函数:
* 参数是另一个函数 loginMethod:(Boolean)->Char
*/
fun show(isLogin:Boolean,loginMethod:(Boolean)->Char){
if(isLogin){
println("登陆成功")
val r = loginMethod(true)
println(r)
}else{
println("登陆失败")
val r = loginMethod(false)
println(r)
}
}
2.Lamba表达式
fun main(){
// 1.空参 空返回值 没有具体实现的函数,不能调用
var m1:()->Unit
// 2. 没有具体实现 不能调用
var m2 :(Int , Int) -> Int
var m3 :(String , Double) -> String
var m4 :(String,Double?) -> Any?
// n1 n2 代表两个参数 返回值是n1+n2
var m5 :(Int , Int) -> Int = { n1 ,n2 -> n1+n2 }
println(m5(1,2))
var m6 = { n1:Int,n2:Int -> n1 + n2 }
println(m6(1,2))
// str1,str2 代表的是两个参数 ->右边的是方法的具体实现
var m7 : (String ,String) -> Unit = {
str1,str2 ->
println("str1 :$str1,str2:$str2")
}
m7("1","2")
// 把参数 str 返回回去
var m8 :(String) -> String = { str -> str}
println(m8("m8"))
// it 代表的是 参数
var m9 : (Int) -> Unit = {
when(it){
1 -> println("yi")
in 2..100 -> println("区间")
else -> println("其他")
}
}
// a,b,c 代表的是三个参数 ->右边的是方法的具体实现
var m10 : (Int,Int,Int) -> Unit = {
a,b,c ->
println("a : $a , b : $b, c: $c")
}
var m11 = { println("m11")}
// sex 是参数 这样写等同于写在()里
var m12 = {sex : Char -> if(sex == 'M') "Man" else "Woman"}
println(m12('M'))
// 覆盖函数
var m13 = {n1: Int -> println("m13 : $n1")}
// 覆盖
m13 = { println("覆盖 $it")}
println(m13(999))
// 要打印 又要返回值
var m14 = {n1 : Int -> println("打印:$n1")
n1 + 10000
}
println(m14(88))
}
3. 高阶函数
无返回值的高阶函数
// 函数的调用
// {} 中的内容 就是 responseResult:(Boolean) -> Unit 的实现 it就是传入的Boolean类型的参数
login("aaa","bbb"){
// 这里是高阶函数的实现
if(it) println("登录成功") else println("登录失败")
}
// 对外暴露的登录方法 responseResult 是高阶函数的方法名
fun login(userName:String,pwd:String,responseResult:(Boolean) -> Unit){
loginEngine(userName, pwd, responseResult)
}
// 私有的 不对外暴露的登录方法
private fun loginEngine(userName:String,pwd:String,responseResult:(Boolean) -> Unit){
// 在这里进行登录操作
val DB_USER_NAME = "aaa";
val DB_USER_PWD = "bbb";
if(userName == DB_USER_NAME && pwd == DB_USER_PWD){
// TODO 登录成功
responseResult(true)
}else{
// TODO 登录失败
responseResult(false)
}
}
有返回值的高阶函数
// 有返回值的高阶函数
login1(){
true // 这个就是高阶函数的返回值
}
// 有返回值的高阶函数
fun login1(mm:()->Boolean){
}
源码中常用的高阶函数
// T 调用myRun的类型 也就是myRun是T的扩展函数
// mm 是高阶函数的函数名 高阶函数是T的匿名函数 返回值为R
fun <T,R> T.myRun(mm : T.() -> R) : R{
return mm()
}
fun main(){
// 调用myRun
val name = "aaaa"
// name是String类型,这里的T == String
// 那么这里的调用高阶函数就是T.length 也就是name.length 返回值是根据{}里的高阶函数实现返回的
name.myRun {
length
}
}
// 高阶函数是 T的匿名函数 也就是input.mm()
// 返回值是高阶函数的返回值
fun <T,R> myWith(input:T,mm:T.() -> R) : R{
return input.mm()
}
// 调用myWith
fun main(){
myWith("aaaaa"){
// 这里是高阶函数的实现
length // 这里相当于 "aaaaa".length
}
}
根据传入的参数,确定是否执行高阶
fun onRun(isRun:Boolean,mm:() -> Unit){
if(isRun) mm()
}
fun main(){
onRun(true){
// 这里是高阶函数的实现
println("执行")
}
}
// TODO