前言: 用了
kotlin
差很少半年时间了,以前是看了中文版的kotlin
入门的,后面使用的时候总感受有些细节的东西并无很好的理解,专门买了份kotlin
的教程,感受不错,本文也是中途一些细节的整理。java
var
用lateinit
延迟初始化,val
用lazy
延迟初始化- 类型后面跟
?
表示可空类型,类型后面不跟?
表示不可空类型- 可空类型使用 :
?.
表示若为null
,则返回null
,不然返回返回对象继续逻辑操做。!!.
表示强制认定为不为null
使用可是最好本身作一下判断,否则等下抛空异常?:
表示当前面为null
的时候,返回?:
后面的值
class X
lateinit var mStr:String //var 延迟初始化
val x:X by lazy{ // val延迟初始化
X()
}
var name: String? = ""
fun a(x: Any): Int {
return name?.length ?: 0
}
val nullable:String? = null //正确 能够为空
val notNull:String = null //报错 不能为空
nullable.length //错误 ,不能够直接使用
notNull.length //正确,不可空的值能够直接使用
nullable!!.length //正确,强认定不为null
nullable?.length //正确,若nullable为空
nullable?.length ?: -1
复制代码
as
类型转换 跟java的类型转换同样,失败则抛异常as?
安全类型转换,转换失败返回null,不会抛异常数组
val stub:Childen = parent as Childen //转换失败 stub不会返回空,会抛异常
val stub:Childen = parent as? Childen //转换失败 stub 能够返回空
复制代码
ClosedRange
的子类,IntRange
最经常使用安全
- 半闭区间 ..
- 开区间 until
- 基本写法:
0..100
表示[0,100]
0 until 100
表示[0,100)
i in 0..100
判断是否在区间[0,100]
中
val range:IntRange = 0..1024 //[0,1024]
val range_exclusive:IntRange = 0 until 1024 //[0,1024) = [0,1023]
val emptyRange:IntRange = 0...-1 //空区间
emptyRange.isEmpty() //判断区间是否为空
//迭代
for(i in range)
复制代码
基本写法: val array:Array<类型> = arrayOf(类型的对象1,类型的对象2,.....) 基本操做:
array[i]
:输入第i
个成员array[i] = 新的类型对象
给第i
个成员赋值bash
array.slice()
截取 可传入区间
eg:0..10 或者 0 until 100
array.joinToString()
转化成String
下面是对应的参数 --separator: CharSequence
:分隔符 默认为,
--prefix: CharSequence
: 增长前缀 默认为""
--postfix: CharSequence
:增长后缀 默认为""
--limit: Int
:截取位置(从1开始而不是从0开始) --truncated
:被limit截取后,后面展现什么 --transform
: 每一个元素进行处理返回处理后的数据
具体例子展现:ide
val arrayOfInt: IntArray = intArrayOf(1,3,5,7)
val arrayOfChar: CharArray = charArrayOf('H', 'e','l','l','o','W','o','r','l','d')
val arrayOfString: Array<String> = arrayOf("我", "是", "码农")
fun main() {
System.out.println(arrayOfString.joinToString(""))
var i:IntRange = 0..100
System.out.println(arrayOfChar.slice(0..7))
var array1 = arrayOfString.joinToString("","前缀","后缀",2,"后面省略",transform = {
//转换
return@joinToString it+"转换"
})
var array2 = arrayOfString.joinToString("","前缀","后缀",3,"后面省略",transform = {
//转换
return@joinToString it+"转换"
})
println(array1)
println(array2)
}
-------------------------------------打印出来的log
我是码农
[H, e, l, l, o, W, o, r]
前缀我转换是转换后面省略后缀
前缀我转换是转换码农转换后缀
复制代码
val TAG = "str"
并不等价与 java中的
public final String TAG = "str"
若是要等价的话
const val TAG = "str"
复制代码
具体的能够看一下反编译
val TAG = "str"
的字节码跟public final String TAG = "str"
有什么不一样~ 里面能够看到val
虽然不可赋值,可是它并非编译器常量,而是一个变量。也就是编译期并非替换成常量来进行的,因此后期仍是能够通过反射进行修改! 若是要像java中定义出编译期常量的话public final String TAG = "str"
则须要使用到const
这里反编译出来的跟java
中的就相似了。函数
本质函数也是一个成员,只不过它是一段代码块post
val int2Long = fun(x:Int):Long{
return x.toLong()
}
复制代码
本质:匿名函数 写法:{[参数列表]->[函数体,最后一行仍是返回值]} 举例:
val sum = {a:Int,b:Int ->a+b}
调用: -- 用()进行调用 -- 等价于 invoke() --eg: sum(1,2) 或者 sum.invoke(1,2)
简化: -- 函数参数参数调用是最后一位Lambda
能够移出去 -- 函数参数只有一个Lambda
,调用时小括号可省略 --Lambda
只有一个参数可默认为it
-- 入参、返回值与形参一直的函数能够用函数引用的方式做为实参传入ui
示例一下:this
//首先 先看下Arrays里面的forEatch方法
public inline fun CharArray.forEach(action: (Char) -> Unit): Unit {
for (element in this) action(element)
}
-------------------------------------------------
接下来,代码中调用
---------------------------------------------------
val arrayOfChar: CharArray = charArrayOf('H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd')
//最基本的调用,传入action的代码块
arrayOfChar.forEach(char ->{println(char)})
// 简化
//1. Lambda只有一个参数可默认为it
arrayOfChar.forEach ({println(it)})
// 2. 函数参数参数调用是最后一位Lambda能够移出去
arrayOfChar.forEach(){pritln(it)}
// 3. 函数参数只有一个Lambda,调用时小括号可省略
arrayOfChar.forEach{pritln(it)}
// 4. 入参、返回值与形参一致的函数能够用函数引用的方式做为实参传入
arrayOfChar.forEach(::println)
复制代码
与
java
不一样,kotlin
的操做符容许咱们进行重载。重载的函数须要使用operation
的修饰符标记 例子:spa
// 重写 减号的实例
class TestKotlin(var a:Int) {
operator fun minus(i:Int):Int{
return a - i
}
}
fun main() {
println(TestKotlin(6) - 5)
}
---------------------输入
1
复制代码
不少的操做符那些能够看一下 《Kotlin语言中文站》
infix
修饰的函数,使用时不须要对象.方法名(参数)
,直接 对象 方法名 参数
//定义
class Book { infix fun on(palce:String){...}}
//使用
Book() on "My Name"
复制代码
for
循环的in
把鼠标点击in
可见其循环机制其实是iterator
机制,hasNext()
跟next()
,判断有没有下一个值,有就获取
下面咱们本身自定义一个MyIterator
,跟MyIntList
来演示一下
class MyIterator(val iterator:Iterator<Int>){
operator fun next():Int{
return iterator.next()
}
operator fun hasNext():Boolean{
return iterator.hasNext()
}
}
class MyIntList{
private val list = ArrayList<Int>()
fun add(int:Int){
list.add(int)
}
fun remove(int:Int){
list.remove(int)
}
operator fun iterator():MyIterator{
return MyIterator(list.iterator())
}
}
fun main() {
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
for (i in list){
println(i)
}
}
复制代码
continue
跟
break
) 跟
java
一致,跳过当前循环用
continue
,终止循环用
break
3. 多层循环嵌套的终止结合标签使用
Outter@for(...){
Inner@while(i<0){if(...)break@Outter}
}
复制代码
能够定义标签,对应关键字后面加上@标签,表明跳出到对应的某一层, 举个例子:
fun main() {
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
list.add(4)
list.add(5)
//break到上一层
for (i in list) {
print(" $i")
while (true) {
print(" $i")
break
}
}
println(" ")
//break到制定标签
OutSide@for (i in list) {
print(" $i")
while (true) {
print(" $i")
break@OutSide
}
}
}
---------------------打印---------------
1 1 2 2 3 3 4 4 5 5
1 1
复制代码
if else
分支表达式等与java
的不一样点,它们做为表达式,能够用来赋值,最后一个行的数据等于return
的数据
fun compare():Int{
val i = 10
if (i == 10 ) 1 else 0
}
复制代码
与
java
不一样的是,它也是表达式,最后一行的数据也是当成要返回的值。 可是 注意下面的写法:
return try{x/y}catch(e:Exception){0}finally{...}
复制代码
先执行完try
有异常就跑到catch
,最后finally
的代码会执行,最后再返回值。(若是正常返回0
,抛异常就返回x/y
)
全部参数都有一点:若是传参时有歧义,须要使用具名参数
fun sum(arg1:Int = 3,arg2:Int = 2) = arg1+arg2
复制代码
给函数的实参附上形参
fun sum(arg1:Int,arg2:Int) = arg1+arg2
sum(arg1=2,arg2=3)
复制代码
某个参数能够接受多个值 与
java
不一样的是,它能够不用作最后一个参数,kotlin
支持具名函数,因此它能够放在参数中任意位置。
fun hello (vararg ints:Int,string:String){ ints.forEach(::println)}
使用:
hello(1,2,3,4,string="Hello")
复制代码
*变量名
)应用场景: 只支持展开Array,只用于变长参数列表的实参,不能重载,不是必定意义上的运算符
fun hello (double:Double,vararg ints:Int,string:String){ ints.forEach(::println)}
使用:
val array = intArrayOf(1,2,3,4)
hello(3.0,*array,string="Hello")
复制代码