这是该系列的第一篇,系列文章目录如下:

  1. Kotlin基础:白话文转文言文般的Kotlin常识
  2. Kotlin基础:望文生义的Kotlin集合操作

这个系列记录的是kotlin使用感受,其中也会穿插基础知识点,并通过项目实战代码综合运用这些知识点。

刚接触kotlin就被它的简洁震撼到了(kotlin的作者一定是一个极简主义!)。一起来看下kotlin是怎么通过“断舍离”来实现简洁的:

new 分号 类型

新建对象不需要new关键词。

任何语句的结尾不需要; 但加上也不会有语法错误。

//java
StringBuffer buffer = new StringBuffer();//kotlin
var buffer = StringBuffer()
复制代码
  • varkotlin保留字,用于声明变量。与之对应的是val用于声明常量。
  • 不需要显示指明变量类型,因为kotlin会根据上下文推断变量类型,这种能力称为 “类型推导”
  • 可以通过下面的语法来指定类型:
var buffer: StringBuffer = StringBuffer()
复制代码
  • kotlin中类型是后置的,在变量名后跟上: 类型就可以显示指定类型。同理,它也用于指定函数返回值类型:
fun getMessage(): String{return "message"
}
复制代码
  • fun关键字用于声明函数。

implements extends @Override

//java
public class CheckableActivity extends Activity {final public void setStatus(){}
}public class MyListener implements View.OnClickListener{@Overridepublic void onClick(View v) {}
}//kotlin
class CirclePartyListActivity : Activity() {fun setStatus(){}
}class MyListener : View.OnClickListener{override fun onClick(v: View?) {}
}
复制代码
  • kotlin: 取代了implementsextends保留字。

  • @Override也被override保留字取代并且和函数头同行,kotlin中的override是必须的,而java中是可选的。

  • kotlin中类和方法默认是final的(可省略不写),这意味着默认情况下,类和方法是不允许被继承和重写的(这是为了防止脆弱的基类,即对基类方法的修改会导致子类出现预期之外的行为)。只有通过open保留字显示声明该类或方法可以被继承或重写:

open class A{open fun do(){}
}
复制代码

()

kotlinlambda也更加简约:

//正常情况
view.setOnClickListener({ v -> v.setVisibility(View.INVISIBLE) })
//当lambda是函数的最后一个参数时,可以将其移到括号外面
view.setOnClickListener() { v -> v.setVisibility(View.INVISIBLE) }
//当函数只有一个lambda类型的参数,可以去省去括号
view.setOnClickListener { v -> v.setVisibility(View.INVISIBLE) }
//当lambda只有一个参数,可省去参数列表,在表达式部分用it引用参数
view.setOnClickListener { it.setVisibility(View.INVISIBLE) }
复制代码

getter setter

java中,字段和其访问器的组合被称为属性,kotlin引入了property access syntax,它取代了字段和访问器方法,用这种方式进一步简化上面的代码:

view.setOnClickListener { it.visibility = View.INVISIBLE }
复制代码
  • 所有被定义了gettersetter方法的字段,在kotlin中都可以通过赋值语法来操作。

{ } return

kotlin中的语句和表达式的唯一区别是:表达式有值,而语句没有。如果函数体由单个表达式构成,可以省去花括号和return,并用赋值的=表示将表达式的值赋值给返回值:

//java
public int add(int a, int b){return a+b ;
}//kotlin
fun add(a: Int, b: Int): Int = a+b
复制代码

在 lambda 表达式中包含多条语句或表达式时,若省略return,则默认将最后一个表达式的值作为返回值:

view.setOnTouchListener { v, event ->...//do somethingfalse
}
复制代码

上述代码表示在OnTouchListener.onTouch()中返回 false。

switch-case-break

//java
String color;
switch(colorInt){case Color.RED:color = "red";break;case Color.BLUE:color = "blue";break;default:color = "black";break;
}//kotlin
val color = when (colorInt) {Color.RED -> "red"Color.BLUE -> "blue"else -> "black"
}
复制代码
  • when用于取代switch-case,不需要在每个分支末尾调用break,如果有一个分支命中则会立即返回。
  • when是一个表达式,这意味着它有返回值,返回值等于命中分支中最后一条语句的返回值。

default

java中的default保留字用于接口中默认方法的实现。在kotlin中可以省去它。

//java
public interface IMessage {default String getMessage() {return "default message";}int getMessageId();
}//kotlin
interface IMessage {fun getMessage(): String {return "default message"}fun getMessageId(): Int
}
复制代码
  • Intjava中基本数据类型int的包装类,kotlin中没有基本数据类型。

防御式编程

//java
public class Address {private String country;public String getCountry() {return country;}
}public class Company {private Address address;public Address getAddress() {return address;}
}public class Person {private Company company;public String getCountry() {String country = null;//多次防御式编程if (company != null) {if (company.getAddress() != null) {country = company.getAddress().getCountry();}}return country;}
}//kotlin
fun Person.getCountry(): String? {return this.company?.address?.country
}
复制代码
  • ?.称为 安全调用运算符 ,它把判空检查和一次方法调用合并成一个操作。只有当调用变量不为null时,才会执行调用,否则整个表达式返回null。这意味着,不再需要防御式编程。
  • ?置于类型之后表示这个类型可空,上面的函数声明表示此函数的返回值可能为null
  • 上面的 kotlin 代码为Person类添加了一个getCountry()方法,这种技术叫扩展函数

扩展函数

扩展函数是一个类的成员函数,但它定义在类体外面。这样定义的好处是,可以在任何时候任何地方给类添加功能。

在扩展函数中,可以像类的其他成员函数一样访问类的属性和方法(除了被privateprotected修饰的成员)。还可以通过this引用类的实例,也可以省略它,把上段代码进一步简化:

fun Person.getCountry(): String? {return company?.address?.country
}
复制代码

kotlin预定了很多扩展函数,下面就会用到其中的apply

冗余对象名

编程中经常会遇到“对同一个对象做多次操作”的场景,比如:

Intent intent = new Intent(this, Activity1.class);
intent.setAction("actionA");
Bundle bundle = new Bundle();
bundle.putString("content","hello");
bundle.putString("sender","taylor");
intent.putExtras(bundle);
startActivity(intent);
复制代码

其中,对象intentbundle重复出现若干次,这对于极简主义的kotlin来说不能忍,它的表达方式如下:

Intent(this,Activity1::class.java).apply {action = "actionA"putExtras(Bundle().apply {putString("content","hello")putString("sender","taylor")})startActivity(this)
}
复制代码

其中,apply的定义如下:

//为泛型T对象添加新功能apply(),它接受一个lambda类型的参数block,且lambda调用的发起者是对象本身
public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}//执行lambdablock()//返回调用者自身return this
}
复制代码

对于object.apply{lambda}可以简单的理解为:在object对象上应用lambda操作,并且最终返回object对象本身。所以上述代码也可以写成更加紧凑的形式:

startActivity(Intent(this, Activity1::class.java).apply {action = "actionA"putExtras(Bundle().apply {putString("content", "hello")putString("sender", "taylor")})
})
复制代码

同一类型的预定义扩展函数还包括withletalso。它们的共同点是适用于 “对同一个对象做多次操作” 的场景 。它们的不同点总结如下:

函数 返回值 调用者角色 如何引用调用者
also 调用者本身 作为lambda参数 it
apply 调用者本身 作为lambda接收者 this
let lambda返回值 作为lambda参数 it
with lambda返回值 作为lambda接收者 this
  • kotlin中,发起调用扩展函数的那个对象,叫接收者对象。同理,发起调用lambda的对象叫做lambda接收者
  • 可以将also的源码和apply做对比,更好的理解他们调用者角色的差别:
//为泛型T对象添加新功能also(),它接受一个lambda类型的参数block,且对象是lambda的参数
public inline fun <T> T.also(block: (T) -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block(this)return this
}
复制代码

综合应用

“让 app 中所有被点击的 View 都带上缩放动画”。综合运用上述kotlin知识点实现这个需求之前,先来看看java是如何实现的:

  1. 先定义工具类,该工具类为传入的View分别设置触摸和单击监听器。在按下时播放动画,松手时反向播放动画。
public class ViewUtil {public static void addExtraAnimClickListener(View view, ValueAnimator animator, View.OnClickListener listener) {view.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:animator.start();break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:animator.reverse();break;}//若返回true,则屏蔽了点击事件return false;}});view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (listener != null) {listener.onClick(v);}}});}
}
复制代码
  1. 在界面中新建动画和点击响应逻辑并将它们传递给工具类
Button btn3 = findViewById(R.id.btn3);
//新建动画:变大
ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 1.2f);
animator.setDuration(100);
animator.setInterpolator(new AccelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Float value = ((Float) animation.getAnimatedValue());btn3.setScaleX(value);btn3.setScaleY(value);}
});
//点击响应逻辑
View.OnClickListener onClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(Activity1.this, "spring anim", Toast.LENGTH_LONG).show();}
};
//应用工具类
ViewUtil.addExtraAnimClickListener(btn3, animator, onClickListener);
复制代码

不要眨眼,换kotlin闪亮登场:

  1. 给View添加扩展函数
//扩展函数接收一个动画和一个点击响应逻辑(用lambda表示)
fun View.extraAnimClickListener(animator: ValueAnimator, action: (View) -> Unit) {setOnTouchListener { v, event ->when (event.action) {MotionEvent.ACTION_DOWN -> animator.start()MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> animator.reverse()}false}setOnClickListener { action(this) }
}
复制代码
  1. 应用扩展函数
btnSpringAnim.extraAnimClickListener(ValueAnimator.ofFloat(1.0f, 1.15f).apply {interpolator = AccelerateInterpolator()duration = 100addUpdateListener {btnSpringAnim.scaleX = it.animatedValue as FloatbtnSpringAnim.scaleY = it.animatedValue as Float}
}) { Toast.makeText(this, "spring anim", Toast.LENGTH_LONG).show() }
复制代码
  • btnSpringAnim是一个Button控件的id(只要装了kotlin插件,就不需要findViewById())
  • as保留字用于类型强制转换。
  • 是不是有一种 “白话文转文言文” 的感觉,kotlin凭借着极强的表达力用将近 1/3 的代码量完成了功能。

知识点总结

  • var保留词用于声明变量,val保留词用于声明常量。大多数情况下不需要显示指明变量类型,kotlin 具有类型推导能力,会根据上下文自动推断类型。
  • fun保留字用于声明函数。
  • override保留字表示重写父类方法或者实现接口中的抽象方法,与 java 不同的是,它必须显示出现在重写方法前( java 允许省略)。
  • as保留字用于类型强制转换。
  • kotlin 中类型是后置的,在变量名或函数参数列表后跟上: 类型就可以显示指定类型。
  • :还用于继承类(取代extends)、实现接口(取代implements)。
  • 新建对象时不需要new,而是直接调用构造函数。
  • 语句末尾不需要; 但加上也不会有语法错误。
  • kotlin 中类和方法默认是final的,他们不能被继承和重写。只有通过加上open后才能被继承和重写。
  • kotlin 中没有基本数据类型,而是用其对应的包装类表示。
  • 给接口方法添加默认实现时不需要default关键字。
  • kotlin 中的语句和表达式的唯一区别是:表达式有值,而语句没有。
  • 如果函数体由单个表达式构成,可以省去花括号和return。
  • when保留字用于取代switch-case,而且它是一个表达式,返回值是命中分支中最后一表达式的值。
  • kotlin 引入了property access syntax,不再需要getter和setter方法,可以直接对属性赋值。
  • ?.称为 安全调用运算符 ,只有当调用变量不为null时,才会执行调用,否则整个表达式返回null。这样就避免了防御式编程。
  • ?置于类型之后表示这个类型的变量或返回值值可能为null
  • kotlin 使用扩展函数,可以在类体外给类新增方法。
  • kotlin 预定了很多扩展函数,其中有一类适用于“对同一个对象做多次操作”。包括also()apply()let()with()

最近开始学习 kotlin ,研读《Kotlin实战》的同时,在项目中加以运用。这个系列会不断地新增来自书本和实践中的新发现。希望对你能有所帮助~~

Kotlin基础:白话文转文言文般的Kotlin常识相关推荐

  1. Kotlin基础学习(一)—— Kotlin 简介

    一.背景 2017年 的Google I/O大会上,Kotlin称为官方的Android开发语言. 发明公司:JetBrains(最负盛名的IDE创造者,包括Android Studio.Intell ...

  2. 第一章 kotlin基础知识

    第一章 kotlin基础知识 文章目录 第一章 kotlin基础知识 前言 一.kotlin是什么? 二.kotlin基础知识 1.变量的声明 2.函数定义的几种方式 3.字符串与数字的转换 4.数组 ...

  3. Kotlin基础语法(上)

    文章目录 Kotlin基础语法(下) Kotlin基础语法(上) 输出Hello world!!! 变量与输出 kotlin常见数据类型 变量的取值范围 kotlin函数 kotlin布尔类型 kot ...

  4. Kotlin基础学习 17

    目录 1.Kotlin语言的过滤函数-filter 2.Kotlin语言的合并函数-zip 3.Kotlin语言的函数式编程 4.Kotlin语言的互操作性与可空性 5.单例模式 6.注解@Jvmna ...

  5. Kotlin学习(一):Kotlin基础知识

    Kotlin学习(一):Kotlin基础知识 定义变量常量 在Kotlin中,定义变量时有以下几点与java不同: 位置不同:在 Kotlin 中,数据类型要放到变量后面,并且用冒号(:)分隔,这正好 ...

  6. Kotlin 基础学习

    学! 原文:https://blog.csdn.net/CrazyApes/article/details/122091459 文章目录 Kotlin 线上编写 变量 lateinit延迟初始化 空安 ...

  7. Kotlin基础学习(1)

    Kotlin基础学习(1) 本文主要讲解kotlin的部分基础知识,并不是全部基础. 提示:纯属个人理解,如有理解错误,欢迎留言指正批评. 一.Null检查机制 kotlin对于声明可为空的参数,使用 ...

  8. Kotlin 基础——Map集合详解

    Kotlin基础--Map集合详解 一.声明和创建Map集合 二.使用Map的方法 三.遍历Map四种方式 四.可变的Map Kotlin的Map集合用于保存key-value对,其也被分为可变的和不 ...

  9. Kotlin Bootcamp 自学(2):Kotlin基础

    Kotlin Bootcamp 自学(2):Kotlin基础 目录 Kotlin Bootcamp 自学(2):Kotlin基础 前言 运算符与数据类型 (Operators and Types) 数 ...

最新文章

  1. python3—廖雪峰之练习(三)
  2. iphone开发 如何在NSMutableDictionary中放入基本数据类型
  3. ROS2学习(七).ROS概念 - ROS客户端库(Ros Client Library)
  4. WinCE的网络驱动实现原理
  5. bobsmith电路阻抗原理_串联谐振原理全解析 - 赫兹电力
  6. 程序流程三控制,顺序控制,分支控制,循环控制综合练习题
  7. 系统集成项目管理工程师知识点集锦
  8. 请问smartadmin中如何只用其treeview 组件?
  9. android 红外遥控程序,基于Dragonboard 410c android系统红外遥控功能的实现方法
  10. 二分图判定 hdu5285 wyh2000 and pupil
  11. org.apache.flink.util.FlinkRuntimeException: Exceeded checkpoint tolerable failure threshold
  12. 【看表情包学Linux】文件描述符 | 重定向 Redirection | dup2 函数 | 缓冲区的理解 (Cache)
  13. Arduino与Proteus仿真实例-继电器驱动仿真
  14. TMS320F280049C 学习笔记11 控制率加速器 CLA 例程
  15. Android 10 Settings应用如何去掉一级菜单定时开关机
  16. Linux下安装钉钉
  17. 计算机网络教程试题库,计算机网络教程_复习题及答案.doc
  18. 苹果核”乔布斯不为人知的九件事
  19. 扫地机器人朋友圈文案_有关扫地机器人的文案
  20. 前端小项目-Thunder Raid(全民飞机大战)-html+css+js 含视频课程+全套代码

热门文章

  1. python 贴吧自动回复_python 几行代码实现自动回复功能
  2. python获取财务数据_「净利润增长率」使用python获取股票“净利润同比增长率”等“上市公司成长能力”数据 - seo实验室...
  3. 显示器点距 测试软件,液晶显示器常见、尺寸、分辨率、点距
  4. VC++如何通过代码自动弹出Windows系统的一些窗口(附源码)
  5. OneDrive和OneDrive for Business映射到本地网络驱动器
  6. 从开发零基础到登上Steam和Oculus:一个VR游戏开发者的自述
  7. COMP9021笔记
  8. 最新《VRay 2.0 for sketchup渲染教程》发布芹
  9. oracle 列转行 带逗号_oracle wm_concat 列转行 逗号分隔
  10. 自定义设置电脑屏保(.scr文件)