kotlin的学习

懒得排版了。 需要查看的直接全局搜索即可。

类,抽象类,接口,继承,实现
类想要被继承,需要增加open修饰字符,abstract类型默认可以被继承,open修饰的类中不能存在抽象方法。
class MainActivity
open class MainActivity
abstract class BaseActivity
interface OnClickListener
class MainActivity : AppCompatActivity()
class MainActivity : AppCompatActivity(), MyListener {}

方法定义
fun goNext(int: Intent): Int {
var num = 1;
return num;
}
Fun 代表方法,固定字段
Int 代表方法返回类型
goNext 方法名
intent 临时参数名
Intent 参数类型
return 为返回值
能一行代码返回值,可以使用下面方法
override fun layoutResID(): Int = R.layout.activity_login

方法复写
override fun onClick(o: Any, view: View) {}//其中any代表可以任意类型

数据类型与定义
Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double、Char 等。不同于 Java 的是,字符不属于数值类型,是一个独立的数据类型。和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作(char不能使用==来比对数字),Char 必需是单引号 ’ 包含起来的。比如普通字符 ‘0’,‘a’。

Doubles 默认写法: 123.5, 123.5e10
Floats 使用 f 或者 F 后缀:123.5f
你可以使用下划线使数字常量更易读:
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
val a: Int = 10000
var str : String = “123123”

数据转换
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char

循环控制
for (item in array7) {
println(item)
}

for ((index, value) in List.withIndex()) {
LOG(“下标KaTeX parse error: Expected 'EOF', got '\t' at position 6: index\̲t̲处的值为value”)
}

for (i in List.size downTo 0) {//输出的index为size-1,size-2…0
LOG(“逆向循环$i”)
}

var mindex = List.iterator()
while (mindex.hasNext()) {
LOG(“hasnext的数据----》” + mindex.next())
}

val it = array7.iterator()
for (item in it.iterator()) {
println(item)
}

val it1 = array7.iterator()
it1.forEach {
println(it)
}

for (st in List.indices) {//输出的st为0,1…,List.size-1
LOG(“第$st 数据是” + List.get(st))
}

when类似于java中的switch函数(其中else等同于default)
when (0) {
in 1…10 -> Log.d(“main”, “x is in the range”)
!in 10…20 -> Log.d(“main”, “x is outside the range”)
else -> Log.d(“main”, “none of the above”)
}

Immutable(不可变集合)
1.创建一个空集合(两种方式)
//var list2: List = listOf()
var nullList = listOf()
LOG(nullList.toString())
输出:[ ]
2.创建一个一个或多个元素的集合
var list2: List = listOf(5)
LOG(list2.toString())
var list2: List = listOf(5,2,3)
LOG(list2.toString())
输出:[5, 2, 3]

set中不允许出现重复值
var qqNum = setOf(1, 1, 3213124, 5655433, 424234)
输出:[1, 3213124, 5655433, 424234]

map中不允许出现重复key
val airPorts = mapOf(
Pair(“name”, “小明”), Pair(“age”, “18”), Pair(“gender”, “男”), Pair(“age”, “18”)
)
输出:{name=小明, age=18, gender=男}

Mutable(可变集合)(List)
1.创建空集合(必须指定存储类型)
var nullchangeList = mutableListOf()
2.创建非空集合
var canChangeList = mutableListOf(“baidu”, “google”, “sougou”)
3.给集合中增加数据
canChangeList.add(“tecent”)
4.给集合中增加集合
nullchangeList.addAll(canChangeList)
5.给集合中指定位置增加数据
canChangeList.add(4, “JD”)
6.集合中的删除使用remove函数,删除指定位置的使用removeAt函数

mutableSetOf相比setof函数得到的set对象,长度可增加,可删除,操作符较多,值不能相同
mutableMapOf相比mapof函数得到的map对象,长度可增加,可删除,操作符较多,key不能相同
下面是map的另一种构造方式。以前大家使用的为put
var map = mutableMapOf<String, String>()
map[“n”] = “我是”
map[“a”] = “一个”
map[“m”] = “好的”
map[“d”] = “网络”
map[“n”] = “工程师”
LOG(map.toString())
map.keys获取map中所有key值,返回MutableSet对象
map.values.获取map中所有的value值,返回MutableCollection对象
map.forEach {//map的遍历
it.key
it.value
}
for ((key, value) in map) {//map的遍历
LOG(key)
LOG(value)
}
map.mapKeys {
//“变种key”+it.key
LOG(“遍历得到的key–” + it.key)
LOG(“遍历得到的value–” + it.value)
}
该函数得到返回的是一个mutablemap,如果{}中对key做了操作,则新map的key改变。{}中可以实现对所有key,所有value的遍历。 另外有mapValues有同等效果。
airPorts.toSortedMap()排序。 按照字母序进行。先大写后小写按照A…Za…

将不可变集合转换成可变集合(tomutable***())
var canchan = nullList.toMutableList()
canchan.add(1)

airPorts.toMutableMap()
qqNum.toMutableSet()

数组Array
创建固定Array —arrayOf
private val permissions = arrayOf(
“android.permission.CAMERA”,
“android.permission.READ_EXTERNAL_STORAGE”,
“android.permission.WRITE_EXTERNAL_STORAGE”
)
val array = arrayOf(“3”, “323”)

创建长度为5,内容均为字符串0的数组
val ret = Array(5) { “0” }
输出:
2019-07-17 15:07:38.060 30063-30063/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:07:38.061 30063-30063/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:07:38.061 30063-30063/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:07:38.061 30063-30063/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:07:38.061 30063-30063/com.oms.omsproject I/LoginActivity: 0

使用闭包创建数组
val ret = Array(5) { i ->
(i * 2).toString()
}
输出:
2019-07-17 15:14:05.055 30284-30284/? I/LoginActivity: 0
2019-07-17 15:14:05.055 30284-30284/? I/LoginActivity: 2
2019-07-17 15:14:05.055 30284-30284/? I/LoginActivity: 4
2019-07-17 15:14:05.056 30284-30284/? I/LoginActivity: 6
2019-07-17 15:14:05.056 30284-30284/? I/LoginActivity: 8

创建arrayList(继承mutableList)
val array = arrayListOf(“3”, “323”)

创建固定长度内容可为null的数组
val array = arrayOfNulls(6)
输出
2019-07-17 15:20:32.357 30690-30690/com.oms.omsproject I/LoginActivity: null
2019-07-17 15:20:32.357 30690-30690/com.oms.omsproject I/LoginActivity: null
2019-07-17 15:20:32.357 30690-30690/com.oms.omsproject I/LoginActivity: null

创建内容对应基本类型的数组

对应
val intArray = IntArray(2)
val doubleArray = DoubleArray(2)
val booleanArray = BooleanArray(2)
val charArray = CharArray(2)

输出
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: 0
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: 0.0
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: 0.0
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: false
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: false
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: ��
2019-07-17 15:47:33.256 31571-31571/com.oms.omsproject I/LoginActivity: ��

Kotlin中@JvmOverloads 注解
在Kotlin中@JvmOverloads注解的作用就是:在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
可能还是云里雾里,直接上代码,代码解释一切:
如果我们再kotlin中写如下代码:
fun f(a: String, b: Int = 0, c: String=“abc”){

}
相当于在Java中声明
void f(String a, int b, String c){
}
默认参数没有起到任何作用。
但是如果使用的了@JvmOverloads注解:
@JvmOverloads fun f(a: String, b: Int=0, c:String=“abc”){
}
相当于在Java中声明了3个方法:
void f(String a)void f(String a, int b)void f(String a, int b, String c)
是不是很方便,再也不用写那么多重载方法了。
注:该注解也可用在构造方法和静态方法。
class MyLayout: RelativeLayout {

@JvmOverloads
constructor(context:Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0): super(context, attributeSet, defStyleAttr)
}
相当Java中的:
public class MyLayout extends RelativeLayout {
public MyLayout(Context context) {
this(context, null);
}

public MyLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

}

修饰符
Kotlin的可见修饰符与Java类似,但是默认的可见性不一样,如果省略修饰符:Java默认包私有,Kotlin默认声明是public
private val a=“该属性不能被子类访问”
protected var b=“该属性能被子类访问”
internal var c=“同一模块下被访问”
var d=“到处都可以被访问”
四种修饰词 private,protected,internal,public,默认的修饰词是public。这些修饰词可以用在类,对象,接口,构造函数,属性以及属性的set()中。
包级别的使用修饰词:
package com.xingen.kotlin.day2017529.pm
private fun test1(){}
public var v=“任何地方都可以见”
private var v2=“只有在本源文件中可见”
internal val v3=“同一模块下可见”
注意点:
protected 在 “top-level” 中不可以使用,即不能修饰包级别的方法或者属性等
private 声明在包含声明的源文件中可见
internal 声明,在同一模块中的任何地方可见

字符串模板
var siteName = “字符串模板”
LOG("初始化名称:$siteName ")

kotlin的三目运算
kotlin中不再有java中的三目运算格式,比如a>b?a:b
取而代之的是直接用if else模式
格式:if(a>b) a else b

vararg可变参数
varary标记的参数,调用方法时可以传可以不传,也可以传多个
/**

  • log 输出
    */
    fun log(msg: String, vararg tags: String) {
    if (tags.isEmpty()) {
    CommonUtils.log(msg, TAG)
    } else {
    CommonUtils.log(msg, tags[0])
    }
    }
    调用log(12123123), 也可以log(1213,”flag“,”main”)

运算符
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b), a.mod(b) (deprecated)
a…b a.rangeTo(b)
位运算符对照表:
shl(bits) – 有符号左移 (相当于 Java’s <<)
shr(bits) – 有符号右移 (相当于 Java’s >>)
ushr(bits) – 无符号右移 (相当于 Java’s >>>) and(bits) – 按位与 or(bits) – 按位或
xor(bits) – 按位异或
inv(bits) – 按位翻转

空安全检查
如果你的变量支持null值,那么在你之后使用该变量时,Kotlin都会在编译期提醒你检测空指针问题:

1.使用双!!可以消除报错,但是如果str是空值,这里会抛出运行时异常,程序退出
val str: String? = null
str!!.length
报错:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.oms.omsproject/com.oms.touchpoint.view.login.LoginActivity}: kotlin.KotlinNullPointerException

2.使用?来消除报错,该方法会优先检测当前变量是否为null,如果为true返回null值,否则调用后面的变量\函数。这里控制台输出Null,程序不闪退
val str: String? = null
var len: Int? = str?.length
log(len.toString())

或者str?:”默认值”

Any和Object
1.Any中定义的方法有:toString()、equals()、hashCode() 3个
2.Object类中定义的方法有:toString()、equals()、hashCode()、getClass()、clone()、finalize()、notify()、notifyAll()、wait()、wait(long)、wait(long,int) 11个
3.联系:Kotlin编译器将kotlin.Any和java.lang.Object类视作两个不同的类,但是在运行时它们俩就是一样的。你可以打印:println(Any().javaClass) ,发现打印出“class java.lang.Object”,
log(Any().javaClass.toString())
log(Object().javaClass.toString())
输出
2019-07-17 16:56:31.336 32508-32508/LoginActivity: class java.lang.Object
2019-07-17 16:56:31.336 32508-32508/LoginActivity: class java.lang.Object
4.null非Any或者Object的子类。 当可能为空的参数向上转型时会报错。

Unit对象
只有一个值的类型:“Unit”对象。这种类型对应于Java中的“void”类型。
package kotlin
/**

  • The type with only one value: the Unit object. This type corresponds to the void type in Java.
    */
    public object Unit {
    override fun toString() = “kotlin.Unit”
    }

is 运算符
is运算符检测一个表达式是否是某类型的实例
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// obj 在该条件分支内自动转换成 String
return obj.length
}
// 在离开类型检测分支后,obj 仍然是 Any 类型
return null
}

安全转换 as
1.首先Kotlin中的强制类型转换在语法上与Java不同,假设我们有以下2个Java类:
public class A { }
public class B extends A{
}
B是A的子类,我们通过下面的Kotlin代码将B类对象先向上转型为A类,再强制转换为B类
var a: A = B()
var b: B = a as B

2.以上代码肯定是没问题的,但是如果a变量本身就是A类对象呢?
var a: A = A()
var b: B = a as B
很明显这时候如果运行代码会抛出ClassCastException:
Kotlin为我们提供了一种安全的转换方案如下:
var a: A = A()
var b: B? = a as? B
我们让B类型支持null后通过as?进行强制转换,如果无法转换不再会抛出ClassCastException,而是返回一个null值,之后的内容我们只需校验b变量为null的情况,从而保证程序的健壮性。

数组参数前的星号的作用
先看下面的方法,initview方法中调用getItem方法,传入的是Array类型的参数。
override fun initView() {
var temp = arrayOf(“1”, “2”, “3”)
getItem(temp)
}
fun getItem(str: Array) {
str.forEach {
log(it)
}
}
下面我们使用
来处理. 由前面的知识可以知道vararg标记的参数,是可变长度参数,可以有多个。 调用getItem方法时,传如array类型的前面加了。 说明的作用是对数组的拆分。
override fun initView() {
var temp = arrayOf(“1”, “2”, “3”)
getItem(*temp)
}
fun getItem(vararg str: String) {
str.forEach {
log(it.toString())
}
}
将数组展开并传入到可变参数中,这很有用!

析构声明
在Kotlin语言中,可以通过析构声明单独提取某个对象中的某些字段。看一个例子:
data class Person(var id: Int, var age: Int, var name: String)

fun main(args: Array) {
val person = Person(1, 28, “Scott Smith”)
val (id, age, name) = person
println(name)
}
析构声明从一定程度上减少了一些样板代码的编写,更令人惊喜的是,它还可以用在循环和map,甚至lambda表达式中:
data class Person(var id: Int, var age: Int, var name: String)
fun func(init: (id: Int, name: String) -> Unit) {
init(1, “Scott Smith”)
}

fun main(args: Array) {
val person = Person(1, 28, “Scott Smith”)
val list = arrayListOf(person)
for ((id, _, name) in list) {
println("$id : KaTeX parse error: Expected 'EOF', got '}' at position 12: name") }̲ val map = …key : $value")
}

func { a, b ->
    println("$a : $b")
}

}
注意:如果要对非数据类进行析构处理,你需要手动实现componentN系列函数。这里,我们依然以Person类为例。如果Person是一个非数据类,为了正确析构,你必须这样做:
class Person(var id: Int, var age: Int, var name: String) {
operator fun component1(): Int {
return id
}

operator fun component2(): Int {
    return age
}

operator fun component3(): String {
    return name
}

}
KaTeX parse error: Expected 'EOF', got '&' at position 122: …aseUrl+"?page=1&̲size=10"//当然这些数…baseUrl?page=KaTeX parse error: Expected 'EOF', got '&' at position 5: page&̲size=size"

=
==判断值是否相等,===判断值及引用是否完全相等。

Kotlin 双冒号 :: 使用
Kotlin 中 双冒号操作符 表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法。先来看一下例子:
fun main(args: Array) {
println(lock(“param1”, “param2”, ::getResult))
}
/**

  • @param str1 参数1
  • @param str2 参数2
    */
    fun getResult(str1: String, str2: String): String = “result is {$str1 , $str2}”

/**

  • @param p1 参数1
  • @param p2 参数2
  • @param method 方法名称
    */
    fun lock(p1: String, p2: String, method: (str1: String, str2: String) -> String): String {
    return method(p1, p2)
    这里需要注意的是,lock 函数 的第三个参数传入 method 时,要确定参数个数、类型、返回值都和其形参一致。

输出结果:
result is {param1 , param2}

一般情况,我们调用当前类的方法 this 都是可省略的,这里之所以不可省略的原因是
为了防止作用域混淆 , :: 调用的函数如果是类的成员函数或者是扩展函数,必须使用限定符,比如this

override fun initView() {//调用
log(test().toString())
}
private fun isOdd(x: Int) = x % 2 != 0
private fun test(): Any {
var list = listOf(1, 2, 3, 4, 5)
return (list.filter(this::isOdd))
}
同时,要得到类的Class对象一样需要使用到::
var bannerData: ActivityBean = Gson().fromJson(str, ActivityBean::class.java)

Kotlin中如何快速findviewbyid
kotlin中可以不使用butterknife插件,直接使用id更为方便。
xml中:

kotlin中
import kotlinx.android.synthetic.main.activity_login.*
btn_login.setOnClickListener(object : android.view.View.OnClickListener {
override fun onClick(p0: View?) {
}
})
with快速得到对象属性值
对对象使用,可以直接在lamda函数块中直接取对象属性。安卓中常用在recyclerView的onBindViewHolder方法中用于数据与view的绑定
val user = User(“Kotlin”, 1, “1111111”)
val result = with(user) {
log(“my name is $name, I am $age years old, my phone number is $phone”)
age
}
log(“result: $result”)
输出
/LoginActivity: my name is Kotlin, I am 1 years old, my phone number is 1111111
/LoginActivity: result: 1
with(user) {
Holder.let {
tvNewsTitle.text = name
tvNewsSummary.text = age.toString()
tvExtraInf.text = phone
}
}

let操作符
1.java中判空代码
if (a != null){
System.out.println(“a”);
}else {
System.out.println(“null”);
}
使用let等同于下面的代码(?: 不为空的执行)
var a: String? = null
a?.let { log(a.toString()) } ?: a.let { log(“这个是为空的状态”) }
}
2.需要去明确一个变量所处特定的作用域范围内可以使用
mVideoPlayer?.setVideoView(activity.course_video_view)
mVideoPlayer?.setControllerView(activity.course_video_controller_view)
mVideoPlayer?.setCurtainView(activity.course_video_curtain_view)
优雅的使用
mVideoPlayer?.let {
it.setVideoView(activity.course_video_view)
it.setControllerView(activity.course_video_controller_view)
it.setCurtainView(activity.course_video_curtain_view)
}

run操作符
run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。
val user = User(“Kotlin”, 1, “1111111”)
val result = user.run {
log(“my name is $name, I am $age years old, my phone number is $phone”)
age
}
log(“result: $result”)

result = user.run {
log(“my name is $name, I am $age years old, my phone number is $phone”)
return@run 123123
}
log(“result: $result”)
输出:
my name is Kotlin, I am 1 years old, my phone number is 1111111
result: 1
my name is Kotlin, I am 1 years old, my phone number is 1111111
result: 123123

适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理

apply操作符
整体作用功能和run函数很像,唯一不同点就是它返回的值是对象本身,而run函数是一个闭包形式返回,返回的是最后一行的值。正是基于这一点差异它的适用场景稍微与run函数有点不一样。apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。或者动态inflate出一个XML的View的时候需要给View绑定数据也会用到,这种情景非常常见。特别是在我们开发中会有一些数据model向View model转化实例化的过程中需要用到。
本来应该这么写:
setOnClickListener(btn_login)
btn_login.alpha = 1f
btn_login.text = “点击”
btn_login.background = getDrawable_(R.mipmap.bg_login)
现在可以这么写
setOnClickListener(btn_login.apply {
alpha = 1f
text = “点击”
background = getDrawable_(R.mipmap.bg_login)
})

also操作符
also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值(java中的空值)。而also函数返回的则是传入对象的本身
val result = “testLet”.also {
log(it.length.toString())
1000
}
log(result)
输出:
2019-07-19 14:20:42.442 27448-27448/com.oms.omsproject I/LoginActivity: 7
2019-07-19 14:20:42.442 27448-27448/com.oms.omsproject I/LoginActivity: testLet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值