文章目录
一. Kotlin 基础知识
1. HelloWorld:
fun main(args: Array<String>){
System.out.println("hello world")
}
2、常见数据类型
3、类型推断
4、取值范围
var aByte:Byte = Byte.MAX_VALUE
var bByte:Byte = Byte.MIN_VALUE
5、函数
fun checkAge(age: Int): Boolean{
if(age > 18) return true else return false
}
6、字符模版
fun diaryGeneraer(placeName: String){
var temple = """今天天气晴朗,万里无云,我们去${placeName}游玩,"""
println(temple)
}
7、字符串比较
与Java中不一样,kotlin中 “==” 和 equals() 一样,equals( , true)是忽略大小写
8、方法参数与null
fun test(){
heat(null) //编译过
heat1(null) //编译不过
}
//参数str可以传null
fun heat(str: String?): String{
return str + "热"
}
//参数str 不可以传null
fun heat1(str: String): String{
return str + "热"
}
9、when 条件语句
fun gradeStudent(score: Int){
when(score){
10 -> println("考了满分")
8 -> println("还可以")
6 -> println("刚好及格")
3 -> println("不行哦")
else -> println("other")
}
}
when 条件语句进阶
fun diaryGenerator(placeName: String){
var diary = """今天天气晴朗,我们去了${placeName}玩,
|刚进大门首先印入眼帘的是${placeName}
|${strNum(placeName.length)}个镏金大字""".trimMargin()
print(diary)
}
fun strNum(score: Int): String{
var result = when(score){
1 -> "一"
2 -> "二"
3 -> "三"
4 -> "四"
else -> "地名太长了"
}
return result
}
9、循环 和 区间
fun main(): Unit{
var nums = 1 .. 100 //闭区间[1, 100]
var result = 0;
for(num in nums){ //循环:in可以把数组中的数字取出来
result = result + num
}
print("结果是" + result)
print("结果是${result}")
}
开区间:
var nums = 1 until 100 //闭区间[1, 100)
step:
var nums = 1 .. 100
for(num in nums step 2){
print("${num} ,")
}
反转:
var nums = 1 .. 100
var nums1 = nums.reversed();
for(num in nums1 step 2){
print("${num} ,")
}
10、list 与 map
- list不带index
var lists = listOf<String>("大米", "鸡蛋", "小米", "薏米")
for(str in lists){
print(str)
}
- list带index
var lists = listOf<String>("大米", "鸡蛋", "小米", "薏米")
for((i, str) in lists.withIndex()){
print("" + i + " " + str)
print("$i $str")
}
- Map
var map = HashMap<String, String>()
map["good"] = "好"
map["yes"] = "是"
map["no"] = "不"
for(str in map){
println(str)
}
println(map.get("good"))
println(map["good"])
11、函数式表达式
//1、
fun add(x: Int, y: Int): Int{
return x + y
}
//2、当函数体只有一句代码时:,
fun add(x: Int, y:Int):Int = x + y
//3、还可以写成这样
var sum = {x:Int, y:Int -> x+y}
var i = sum(3, 5) //调用
//4、
var sum1:(Int, Int) -> Int = {x,y -> x + y}
12、默认参数和具名参数
fun main(): Unit{
sum()
sum(1, 3)
sum(x = 3)
sum(y = 9) //具名参数
}
//默认参数
fun sum(x:Int = 2, y:Int = 5): Int{
return x + y
}
13、Stirng 与 Int 互转
fun main(): Unit{
var str = "123"
var int = 123;
var strInt = "123abc"
int = str.toInt();
str = int.toString();
int = strInt.toInt(); //编译器会报错java.lang.NumberFormatException: For input string: "123abc"
}
14、异常处理
while (true) {
println("请输入数字")
var str = readLine()
try {
var int = str!!.toInt()
}catch (e: Exception){
println("大哥,要输入数字哦")
}
}
15、尾递归优化
二、面向对象
1、继承
open class Fathor{ //被继承需要open
var chactor: String = "性格内向"
open fun action(){ //被复写需要open
println("喜欢思考")
}
}
class Son: Fathor(){
override fun action() { //复写需要override
println("儿子很乖")
}
}
2、接口
interface Iman {
fun say()
}
abstract class Human(var name:String){
abstract fun eat()
}
class Man(name: String) : Human(name), Iman {
override fun eat() {
println("大口吃")
}
override fun say() {
}
}
3、代理和委托 by
interface IWash {
abstract fun wash();
}
class BigHeadChild : IWash {
override fun wash() {
}
}
class SmallHeadFather : IWash by BigHeadChild(){
override fun wash() {
println("我是大头爸爸,儿子帮我洗碗")
BigHeadChild().wash()
}
}
4、单例 object
object BigHeadChild : IWash {
override fun wash() {
}
}
调用的时候()去掉
class SmallHeadFather : IWash by BigHeadChild{
override fun wash() {
println("我是大头爸爸,儿子帮我洗碗")
BigHeadChild.wash()
}
}
5、枚举 和 印章类
枚举:注重数据
fun main(): Unit{
println(Week.星期一)
println(Week.星期一.ordinal)
}
enum class Week{
星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日,
}
印章类:注重类型
fun main(): Unit{
var s1:Son = Son.小小驴()
var s2:Son = Son.骡子()
}
sealed class Son{
fun sayHello(){
println("大家好")
}
class 小小驴() : Son()
class 骡子(): Son()
}
三、高阶函数(参数/返回值为函数 )(forEach,map,flatmap,fold,reduce,filter,takeWhite,let/run,also/apply,with,use)
//maxBy
printGirl(grilList.maxBy { it.height }) //Java 中需要遍历一遍
//minby
printGirl(grilList.minBy { it.height })
//filter
println(grilList.filter {
(it.height > 123) and (it.height < 1234)
})
//map
var result = grilList.map { "${it.name} : ${it.height}" }
println(result)
//any 是否有
println(grilList.any{ it.height == 1253})
//count
println(grilList.count{ it.height <= 1253})
//find 查找第一个符合条件的
println(grilList.find{ it.height == 1253})
//groupBy 根据不同的条件分组
println(grilList.groupBy{ it.address})
println(grilList.groupBy{ it.address}.get("北京"))
println(grilList.groupBy{ it.address}.get("北京")?.forEach { printGirl(it) })
//let
grilList.get(0)?.let { printGirl(it) }
1、let函数适用的场景
参考:https://blog.csdn.net/u013064109/article/details/78786646
场景一: 最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理。
场景二: 然后就是需要去明确一个变量所处特定的作用域范围内可以使用
不使用let,不够优雅
mVideoPlayer?.setVideoView(activity.course_video_view)
mVideoPlayer?.setControllerView(activity.course_video_controller_view)
mVideoPlayer?.setCurtainView(activity.course_video_curtain_view
)
使用let
mVideoPlayer?.let {
it.setVideoView(activity.course_video_view)
it.setControllerView(activity.course_video_controller_view)
it.setCurtainView(activity.course_video_curtain_view)
}
2、with函数的适用的场景
适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上:
没有使用with前:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ArticleSnippet item = getItem(position);
holder.tvNewsTitle.setText(StringUtils.trimToEmpty(item.titleEn));
holder.tvNewsSummary.setText(StringUtils.trimToEmpty(item.summary));
String gradeInfo = "难度:" + item.gradeInfo;
String wordCount = "单词数:" + item.length;
String reviewNum = "读后感:" + item.numReviews;
String extraInfo = gradeInfo + " | " + wordCount + " | " + reviewNum;
holder.tvExtraInfo.setText(extraInfo);
...
}
使用with后: $代替item
override fun onBindViewHolder(holder: ViewHolder, position: Int){
val item = getItem(position)?: return
with(item){
holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
holder.tvExtraInf.text = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
...
}
}
3、run函数的适用场景
适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理。
run函数使用前:
override fun onBindViewHolder(holder: ViewHolder, position: Int){
val item = getItem(position)?: return
with(item){
holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
...
}
}
使用run后:
override fun onBindViewHolder(holder: ViewHolder, position: Int){
getItem(position)?.run{
holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
...
}
}
4、apply 适用场景
整体作用功能和run函数很像,唯一不同点就是它返回的值是对象本身,而run函数是一个闭包形式返回,返回的是最后一行的值。正是基于这一点差异它的适用场景稍微与run函数有点不一样。
apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。或者动态inflate出一个XML的View的时候需要给View绑定数据也会用到,这种情景非常常见。特别是在我们开发中会有一些数据model向View model转化实例化的过程中需要用到。
没有使用apply函数的代码是这样的:
mSheetDialogView = View.inflate(activity, R.layout.layout_sheet_inner, null)
mSheetDialogView.course_comment_tv_label.paint.isFakeBoldText = true
mSheetDialogView.course_comment_tv_confirm.paint.isFakeBoldText = true
mSheetDialogView.course_comment_seek_bar.max = 10
mSheetDialogView.course_comment_seek_bar.progress = 0
使用apply函数后的代码是这样的:
mSheetDialogView = View.inflate(activity, R.layout.layout_sheet_inner, null).apply{
course_comment_tv_label.paint.isFakeBoldText = true
course_comment_tv_score.paint.isFakeBoldText = true
course_comment_seek_bar.max = 10
course_comment_seek_bar.progress = 0
}
多层级判断:
if (mSectionMetaData == null || mSectionMetaData.questionnaire == null || mSectionMetaData.section == null) {
return;}
if (mSectionMetaData.questionnaire.userProject != null) {
renderAnalysis();
return;}
if (mSectionMetaData.section != null) {
fetchQuestionData();
return;}
apply优化后:
mSectionMetaData?.apply{
//mSectionMetaData不为空的时候操作mSectionMetaData
}?.questionnaire?.apply{
//questionnaire不为空的时候操作questionnaire
}?.section?.apply{
//section不为空的时候操作section
}?.sectionArticle?.apply{
//sectionArticle不为空的时候操作sectionArticle
}
四、DSL(特定领域语言)
只有一个参数,且用infix修饰的函数
//书
class Book{
//infix 自定义运算符的中缀表达式。本没有on,自定义一个,不需要类名.方法即可调用
//传入任意类型,返回一个Boolean类型的参数
infix fun on(any: Any): Boolean{
return true
}
}
//桌子
class Desk
fun main(args: Array<String>) {
if(Book() on Desk()){
println("书在桌上")
}
}