一.处理Kotlin代码的方式
1.Kotlin Playgroud 在对应网站trykotlinlang.org上在线试用,不用Andriod框架依赖性
2.Andriod Studio |File|Setting|Plugins|Install JetBrains plugin..|Kotlin下载在2.x版本下,3.x则不用,在Tools|Kotlin|Configuration Kotlin in Project
选择Andriod with Gradle 然后再选择所需模块和Kotlin版本,3.0之后可在创建项目时选中Include Kotlin support
3.使用Java-Kotlin转换器J2K
二.Kotlin语言基础知识
1.Kotlin 定义两种数据类型: var:可变引用,可在初始化后更新
val:只读引用,初始化之后无法赋值
val变量相当与final修饰的Java变量,防止被错误修改,多线程工作时,可以不必担心数据同步操作,@val无法改变指向特定对象实例的引用,但可以修改对象的属性
var list = mutableListOf("a","b","c")//ok
list = mutableListOf("d")//error
list.remove(3)//ok
2.类型推断
var title :String
当变量声明和初始化一起执行,可忽略类型声明
var title:String="Kotlin"
类型推断会导致title = 12报错
Kotlin有类型体系结构,全部显性继承Any类型,相当与Java的对象,有equals、toString、hashCode
在Android Studio中可以用Shift+Ctrl+P快捷键知道类型,类型推荐机制同样可以用于泛型
var persons = listOf(personInstancel1,personInstancel2)
//equal to List
var pair = "Everest" to 8848
//equal to Pair
var pair = Pair("Ever",8848)
//use constructor
二元参数判断取基本类型String和Int最近的Any类型
必要时可以显性定义数据类型var age: Long = 18
省内存可以用Short
3.严格的空保护机制
在Java中的NullPointerExceptions,大多数不是运行期错误,所以Kotlin加入默认情况下不能设置为空值和存储空引用,除非显性定义
//在变量类型声明加?
val age:Int = null//error
val name:String? =null//ok
//但是潜在空对象无法调用其方法
name.toUpperCase()//error
//需要在调用前加判断
3.Kotlin安全调用 val locked: Bollean? = savedInstanceState?.getBoolean("locked")
4.elvis操作符 first operand?:second operand 如果第一个操作数不为null返回否则第二个
5.let 可空变量处理方式
savedInstanceState?.let{
//ok
}
//当不为空执行let之后的代码
6.处理空指针的例子
val textView = findViewById(R.id.textView) as TextView//不可空
val textView = findViewById(R.id.textView) as TextView?//可空
7.转换
Kotlin采用as关键字为转换操作符,处理转换问题
val fragment: Fragment = ProductFragment()
val productFragment: ProductFragment = fragment as ProductFragment//将上面的fragment转变成ProductFragment
非安全型转换as:无法实现,抛出ClassCastException异常
安全型转换 as?:无法实现,返回null
Kotlin支持to+类型名
智能转换 隐性转换
//Fish继承Animal并有自己的方法isHungry()
if(animal is Fish){
animal.isHungey()//此时为fish
}
animal.isHungey()//error 此时为animal
在&&和判空可以应用
fun setView(view :View?){
view ?:throw RunTimeExceptions("View is empty")
//is non-nullable
view.isShown()
}
8.基本数据类型
Byte?、Char?,为"装箱"型表达方式,但是这种方式比较耗内存,对表和数组来讲,影响尤为明显,对于单变量来说就不用担心表达形式
Kotlin针对数字的处理方式不同,数字间没有隐式转换,较小的类型不能隐式转变为较大类型
var weight: Int = 12
var truckweight: Long = weight//error
var truckweight: Long = weight.toLong()
//正确形式
//Kotlin 可以推断类型
val a: Int =1
val b =a+1 //inferred b is Int
val b = a+1L //inferred b is Long
Kotlin 不支持8进制
9.数组
val array = arrayOf(1,2,3)
//建立数组
val array2:Array = arrayOf(1,2,3)
val array3:Array = arrayOf(1,2,3)
val array = arrayOf(1,2,3)//Long数据元素的泛型数组
val array = longArrayOf(1,2,3)//包含Long 数据元素的数组
//kotlin可以指定数组的实际尺寸
val array = arrayOfNulls(3)
val array = Array(5){it*2}//lambda表达式
println(array) // Prints: [ 0,2,4,8,10]
10.字符串
方法可以参考String类文档
val name = "Eva"
val message = "My name is $name"
//$符号将变量置于字符串之中
val message = "My name has ${name.length} characters"
11.数组遍历
val intRange = 1..4//equal to i>=1&&i<=4
val charRange = 'b' .. 'g'
默认步进值为1
for(i in 5 downTo 1) print(i) // 逆向遍历
for(i in 3..6 step 2) print(i)//Prints:35
step设置步长
12.Kotlin为面向表达式语言 var speed = vcurrentSpeed + getAcceleration()
13.if表达式:println(if(x>10)"greater"else"smaller")
val greeting =if(hour<18){
"Good day"
}else {
"Good evening"
}
val message = "You are ${ if(age < 18)"young"else "of age"}
println(message)
14.when表达式,相当与if表达式,但是else 是必需的,要覆盖全部情况
val vehicle = "Car"
when(vehicle){
"Car" , "Bike" -> print("Vehicle")
else ->print("Unmatch")
}
//逗号分开两种不同的情况,
//when还可以判断变量类型
val vehicle = "Car"
when(vehicle){
is String->
is User->
}
//检验特定值范围
val risk = when(risks){
in 1..20 ->"small risk"
!in 21..40->"minor risk"
!in 41..60 ->major risk"
else->"undefined risk"
}
println(risk)
/* 重要一点如果条件包含所有,可以不加else ,编译器会帮你解决问题*/
15.Kotlin循环 for ( item in array){
print(item)
}
可以根据索引,withIndex库方法,可返回IndexedValue属性列表,其中包含一个索引和一个数值
for( (index,value) in array.withIndex() ){
println("Element at $index is $value")
}
其他如while break continue do...while 与java类似
break 语句提供标注形式
val charRange = 'A'..'B'
val intRange = 1..6
outer@ for(value in intRange){
println("Outer loop : $value ")
for(char in charRange){
if(char == 'B')
break@outer
println("$char")
{
}
//prints
Outer loop: 1
A
break@outer 跳到标记循环之后的语句
16.异常处理 Kotlin中全部异常均为非检查型
fun foo(){
throw IOException()
}
fun bar(){
foo()//no need to try-catch block
}
/* Kotlin try表达式定义为表达式,可以返回值*/
//Android 检验是否成功安装
val result = try {
context.packageManager.getPackageInfo("com.text.app",0)
}catch(ex: PackageManager.NameNotFoundException{
false
}
Kotlin try表达式定义为表达式,可以返回值
17. val只有只读性质,在大多数时候可将其视做常量,初始化过程可能延迟
const val MAX_LOG_ENTRIES = 100
@MyLogger(MAX_LOG_ENTRIES)
// value availiable at compile time
class Test{}
//保证在编译期已知,用const关键字
三、函数
1.定义函数
fun main(args: Array){
println("Hello,World!")
}
fun double(i : Int): Int{
return 2*i
}
2.返回函数的形式
fun printSum(a:Int,b:Int): Unit{//不返回值
val sum = a+b
print(sum)
}
fun printSum(a:Int,b:Int): Int{//返回Int
return sum
}
3.vararg参数
可以传任意数量的参数,正常状态下,期待为加载特定类型的泛型数组
fun print Sum(vararg numbers: Int){
val sum = numbers.sum()
print(sum)
}
printSum(1,2,3,4,5)//Prints:15
printSum()//Prints:0
fun printAll(vararg texts: Any){
val allTexts = texts.joinToString(",")
println(allTexts)
}
//Usage
printAll("A",1,,'c')//Prints: A,1,c
4.单表达函数
fun square(x:Int):Int = x*x
//在安卓项目中根据布局
class AddressAdapter : ItemAdapter(){
override fun getLayoutId() = R.layout.choose_address_view
override fun onCreateViewHolder(itemView : View)
ViewHolder(itemView)
}
//独立对象上的链接多项操作
fun textFormatted(text: String,name: String) = text
.trim()
.capitalize()
.replace("{name}", name)
val formatted = textFormated("hello,{name}","Marcin")
println(formatted)
5.命令式编程和声明式编程: 命令式编程范例描述了所需的实际步骤,进而执行某项操作
声明式编程范例描述了期望结果,但无须按照步骤予以实现(行为实现),程序通过表达式或声明
来实现
6.尾递归函数:
tailrec fun getState(state: State, n:Int):State =
if(n<=0) state
else getState(state.nextState(),n-1)
尾递归函数无需担心StackOverflowError,可通过编译器优化递归调用
//尾递归工作方式
public static final State getState(@NotNull State state, int n)
{
while(true){
if(n<=0)return state;
state = state.nextState();
n=n-1;
}
}
7.默认参数值
fun printValue(value: String,prefix:String="",suffix:String=""){
print(prefix)
print(value)
println(suffix)
}
printValue("str")//Prints: str
printValue("str","(",")")//Prints: (str)
8.命名参数语法
对于Kotlin参数,命名参数语法还具有额外的特征,当改变某个参数名时,也许会由于该名称会用于其他项目中,因而将会产生错误。使用命名参数语法,Kotlin库生成器一般会对此谨慎处理
9.顶级函数
//Printer.kt
fun PrintTwo(){
print(2)
}
//将代码编译为Java字节码
public final calss PrintKt{
public static void printTwo(){
System.out.print(2)
}
}
10.顶级函数的底层机制
@file:JvmName("Printer")
相当与java引入Printer.java文件
@file:JvmName("Math")引用数学帮助函数
用修改生成类名的JvmName注解十分有用,有助于解决命名冲突问题
11.局部函数
fun makeStudentList() : List{
var students: List = emptyList()
fun addStudent(name:String,state:Student.State =
Student.State.New){
students +=Student(name,state,courses = emptyList())
}
//...
addStudent("Ada")
addStudent("Donald")
//...
return students
}
12.无返回类型
函数可简化错误抛出机制,如throwError
fun fail () :Nothing = throw Error()
简化单元测试中的错误机制
Nothing是所有类型的子类型,即可空类型和非空类型,同时这也是Nothing被称作空类型的原因,意味着不存在任何值在运行期内包含该类型,无法形成Nothing实例,仅存在从函数返回的错误信息,将其作为返回类型。对于Nothing来说,没有必要添加任何内容以对该类型产生影响
四、类和对象
1.定义类
在Kotlin中是用class关键字定义的 ex. class Person
val person = Person()
在Kotlin文件中无需使用new关键字,在Java文件中使用new 关键字
2.属性
Kotlin用constructor方法相当于Java类的构造方法,替代方法是可以用init代替constructor
//1
class Person{
var name: String
var age:Int
constructor(name:String, age:Int){
this.name = name
this.age = age
}
}
//2
class Person constructor(name:String, age:Int){
var name: String
var age:Int
init{
this.name = name
this.age = age
}
}
3.读-写形式 和 只读属性
用val 关键字 仅生成 getter方法
Kotlin不支持只写属性
4.属性访问语法
Car car = new Car(7.4)
car.setSpeed(9.2)
Double speed = car .getSpeed
5.自定义getter/setter