网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
也必须实现else
,否则报错
fun getScore(name: String) = when(name) {
“Tom” -> “不及格”
“Jim” -> “及格”
“Pony” -> “良好”
“Tony” -> “优秀”
else -> “名字非法”
}
when
支持参数检查
fun checkNumber(num: Number) {
when (num) {
is Int -> println(“Int”)
is Double -> println(“Double”)
else -> println(“others”)
}
}
when
也可不传递形参
使用Boolean使when更加灵活
fun getScore(name: String) = when {
name == “Tom” -> “不及格”
name == “Jim” -> “及格”
name == “Pony” -> “良好”
name == “Tony” -> “优秀”
else -> “名字非法”
}
-> 后不仅可以只执行一行代码,可以多行,看一个比较复杂的例子:
fun getScore(name: String) = when {
//若name以Tom开头则命中此分支
name.startsWith(“Tom”) -> {
//处理
println(“你好,我是Tom开头的同学”)
“不及格”
}
name == “Jim” -> “及格”
name == “Pony” -> “良好”
name == “Tony” -> “优秀”
else -> “名字非法”
}
循环语句
Kotlin
有两种循环方式,while和for-in,while
与java
中的while
没有区别,for-in是对Java for-each
的加强,Kotlin
舍弃了for-i
的写法
while
不再赘述,在学习for-in
之前需要明确一个概念-区间
val range = 0…10 //区间代表[0,10]
for-in
需借助区间来使用
fun main() {
val range = 0…10
for (i in range) { //也可直接for (i in 0…10)
println(i)
}
//输出结果为 从0打印到10
}
0..10
代表双闭区间,如果想使用左闭右开呢,需要借助until
关键字
fun main() {
for (i in 0 until 10) {
println(i)
}
//输出结果为 从0打印到9
}
上述实现是逐步进行相当于i++
,Kotlin
也支持跳步
fun main() {
for (i in 0 until 10 step 2) {
println(i)
}
//输出结果为0,2,4,6,8
}
上述实现都是升序,Kotlin
也可降序循环
fun main() {
for (i in 10 downTo 1) {
println(i)
}
//输出结果为10 - 1
}
for-in
不仅可对区间进行遍历,还可对集合进行遍历,后续在集合处进行展示。
类和对象
类的创建和对象的初始化
在创建页面选择Class
创建
创建Person
类,并声明name
,age
,创建printInfo
方法
class Person {
var name = “”
var age = 0
fun printInfo() {
println(name +"'s age is " + age)
}
}
在main
方法中声明一个Person
对象并调用printInfo
方法
fun main() {
val person = Person()
person.name = “zjm”
person.age = 20
person.printInfo()
}
//结果如下zjm’s age is 20
继承
声明Student
类继承Person
,Kotlin
中继承使用**:**,后接父类的构造,为什么需要构造后续讲解
class Student : Person(){ //此时Person报错
var number = “”
var grade = 0
fun study() {
println(name + “is studying”)
}
}
Person
类当前不可继承,查看Person
对应的java
文件
public final class Person {
…
}
Person
类为final
不可被继承,因此需借助open关键字
只需在Person
类前加上open
open class Person {
…
}
此时Person
的java
文件变为
public class Person {
…
}
此时Student
将不再报错
构造
构造分为主构造和此构造
主构造
主构造直接写在类后面
修改Student
类
class Student(val number: String, val grade: Int) : Person(){
…
}
在创建Student
对象时,如下创建
val student = Student(“1234”, 90)
因之前Person
还有name
和age
,下面修改Person
类的主构造
open class Person(val name: String, val age: Int) {
…
}
此时Student
报错,因为继承Person
时,后边使用的是Person()
无参构造,上面我们修改了Person
的构造,则不存在无参构造了。
再修改Student
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){
…
}
此时不在报错,声明方式如下
val student = Student(“zjm”, 20, “1234”, 90)
在构造时需要进行特殊处理怎么办,Kotlin提供了init结构体,主构造的逻辑可在init
中处理
open class Person(val name: String, val age: Int) {
init {
println(“name is” + name)
println(“age is” + age)
}
}
上述修改都为主构造,那如果类想有多个构造怎么办,此时需借助次构造
次构造
此时实现Student
的另外两个构造
三个参数的构造,name
,age
,number
,grade
不传参默认为``0
无参构造,字符串默认为"",int默认为0
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){
constructor(name: String, age: Int, number: String) : this(name, age, number, 0) {
}
constructor() : this(“”, 0, “”, 0) {
}
…
}
创建如下:
fun main() {
val student1 = Student(“zjm”, 20, “123”, 90)
val student2 = Student(“zjm”, 20, “123”)
val student3 = Student()
}
无主构造
若类不使用主构造,则后续继承类也不需要使用构造即可去掉继承类的()
,次构造可以调用父类构造super
进行初始化,但是次构造的参数在其他地方无法引用
class Student : Person {
constructor(name: String, age: Int, number: String) : super(name, age) {
}
fun study() {
//name,age可使用
println(name + “is studying”)
//使用number则会报错,若number是主构造的参数则可引用
//println(number) 报红
}
}
接口
接口的定义
和Java
中的接口定义类似
interface Study {
fun study()
fun readBooks()
fun doHomework()
}
接口的继承
继承接口只需在后用","
拼接,需实现Study
声明的全部函数
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age), Study{
…
override fun study() {
TODO(“Not yet implemented”)
}
override fun readBooks() {
TODO(“Not yet implemented”)
}
override fun doHomework() {
TODO(“Not yet implemented”)
}
}
Kotlin
支持接口方法的默认实现,JDK1.8
以后也支持此功能,方法有默认实现则继承类无需必须实现此方法
interface Study {
fun study() {
println(“study”)
}
fun readBooks()
fun doHomework()
}
权限修饰符
Java
和Kotlin
的不同如下表所示:
修饰符 | Java | Kotlin |
---|---|---|
public | 所有类可见 | 所有类可见(默认) |
private | 当前类可见 | 当前类可见 |
protected | 当前类,子类,同包下类可见 | 当前类,子类可见 |
default | 同包下类可见(默认) | 无 |
internal | 无 | 同模块下的类可见 |
Kotlin
引入internal
,摒弃了default
使用:
类上
public open class Person(val name: String, val age: Int){…}
变量上
private val value = 1
方法上
private fun test() {
}
数据类和单例类
数据类
数据类则只处理数据相关,与Java Bean
类似,通常需要实现其get
,set
,hashCode
,equals
,toString
等方法
下面实现UserBean
,包含id
,name
,pwd
属性
Java
编写入如下:
public class UserBean {
private String id;
private String name;
private String pwd;
public UserBean() {
}
public UserBean(String id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserBean userBean = (UserBean) o;
return Objects.equals(id, userBean.id) && Objects.equals(name, userBean.name) && Objects.equals(pwd, userBean.pwd);
}
@Override
public int hashCode() {
return Objects.hash(id, name, pwd);
}
@Override
public String toString() {
return “UserBean{” +
“id='” + id + ‘’’ +
“, name='” + name + ‘’’ +
“, pwd='” + pwd + ‘’’ +
‘}’;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
Kotlin
编写此类将变得非常简单,新建一个kt
文件,选择如下:
一行代码即可搞定,Kotlin会自动实现上述方法。
data class UserBean(val id: String, val name: String, val pwd: String)
若无data
关键字,上述方法(hashCode
,equals
,toString
)无法正常运行,去掉data
查看Kotlin
对应的java
文件:
public final class UserBean {
@NotNull
private final String id;
@NotNull
private final String name;
@NotNull
private final String pwd;
@NotNull
public final String getId() {
return this.id;
}
@NotNull
public final String getName() {
return this.name;
}
@NotNull
public final String getPwd() {
return this.pwd;
}
public UserBean(@NotNull String id, @NotNull String name, @NotNull String pwd) {
Intrinsics.checkNotNullParameter(id, “id”);
Intrinsics.checkNotNullParameter(name, “name”);
Intrinsics.checkNotNullParameter(pwd, “pwd”);
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
}
发现上面代码既无hashCode
,equals
,toString
也无set
加上data
且把变量改为var
,对应的java
文件如下:
public final class UserBean {
@NotNull
private String id;
@NotNull
private String name;
@NotNull
private String pwd;
@NotNull
public final String getId() {
return this.id;
}
public final void setId(@NotNull String var1) {
Intrinsics.checkNotNullParameter(var1, “<set-?>”);
this.id = var1;
}
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkNotNullParameter(var1, “<set-?>”);
this.name = var1;
}
@NotNull
public final String getPwd() {
return this.pwd;
}
public final void setPwd(@NotNull String var1) {
Intrinsics.checkNotNullParameter(var1, “<set-?>”);
this.pwd = var1;
}
public UserBean(@NotNull String id, @NotNull String name, @NotNull String pwd) {
Intrinsics.checkNotNullParameter(id, “id”);
Intrinsics.checkNotNullParameter(name, “name”);
Intrinsics.checkNotNullParameter(pwd, “pwd”);
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
@NotNull
public final String component1() {
return this.id;
}
@NotNull
public final String component2() {
return this.name;
}
@NotNull
public final String component3() {
return this.pwd;
}
@NotNull
public final UserBean copy(@NotNull String id, @NotNull String name, @NotNull String pwd) {
Intrinsics.checkNotNullParameter(id, “id”);
Intrinsics.checkNotNullParameter(name, “name”);
Intrinsics.checkNotNullParameter(pwd, “pwd”);
return new UserBean(id, name, pwd);
}
//
F
F
:
s
y
n
t
h
e
t
i
c
m
e
t
h
o
d
p
u
b
l
i
c
s
t
a
t
i
c
U
s
e
r
B
e
a
n
c
o
p
y
FF: synthetic method public static UserBean copy
FF:syntheticmethodpublicstaticUserBeancopydefault(UserBean var0, String var1, String var2, String var3, int var4, Object var5) {
if ((var4 & 1) != 0) {
var1 = var0.id;
}
if ((var4 & 2) != 0) {
var2 = var0.name;
}
if ((var4 & 4) != 0) {
var3 = var0.pwd;
}
return var0.copy(var1, var2, var3);
}
@NotNull
public String toString() {
return “UserBean(id=” + this.id + “, name=” + this.name + “, pwd=” + this.pwd + “)”;
}
public int hashCode() {
String var10000 = this.id;
int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
String var10001 = this.name;
var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;
var10001 = this.pwd;
return var1 + (var10001 != null ? var10001.hashCode() : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof UserBean) {
UserBean var2 = (UserBean)var1;
if (Intrinsics.areEqual(this.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.pwd, var2.pwd)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
此时则和手动编写的java bean
功能一样了,所有方法都可正常运行
单例类
目前Java
使用最广的单例模式的实现如下:
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
public void test() {
…
}
}
在Kotlin
中创建单例类需选择Object
生成代码如下:
object Singleton {
fun test() {
…
}
}
其对应的java
文件如下,和上述使用最多的java
单例实现类似
public final class Singleton {
@NotNull
public static final Singleton INSTANCE;
public final void test() {
}
private Singleton() {
}
static {
Singleton var0 = new Singleton();
INSTANCE = var0;
}
}
使用如下:
fun main() {
Singleton.test() //对应的java代码为Singleton.INSTANCE.test();
}
Lambda
许多高级语言都支持Lambda
,java
在jdk1.8
以后才支持Lamda
语法,Lamda
是Kotlin
的灵魂所在,此小节对Lambda
的基础进行学习,并借助集合练习。
集合的创建和遍历
List
fun main() {
//常规创建
val list = ArrayList()
list.add(1)
list.add(2)
list.add(3)
//listOf不可变,后续不可添加删除,只能查
val list1 = listOf(1, 2, 3 ,4 ,5)
list1.add(6)//报错
//mutableListOf,后续可添加删除
val list2 = mutableListOf(1, 2, 3 ,4 ,5)
list2.add(6)
//循环
for (value in list2) {
println(value)
}
}
Set
set
用法与List
类似,只是把listOf
替换为mapOf
Map
fun main() {
val map = HashMap<String, String>()
map.put(“1”, “zjm”)
map.put(“2”, “ljn”)
//Kotlin中map支持类似下标的赋值和访问
map[“3”] = “lsb”
map[“4”] = “lyx”
println(map[“2”])
println(map.get(“1”))
//不可变
val map1 = mapOf<String, String>(“1” to “zjm”, “2” to “ljn”)
map1[“3”] = “lsb” //报错
//可变
val map2 = mutableMapOf<String, String>(“1” to “zjm”, “2” to “ljn”)
map2[“3”] = “lsb”
for ((key, value) in map) {
println(key + " " + value)
}
}
Lambda的使用
方法在传递参数时都是普通变量,而Lambda
可以传递一段代码
Lambda
表达式的语法结构
{参数名1: 参数类型, 参数名2:参数类型 -> 函数体}
Kotlin
的list
提供了maxByOrNull
函数,返回当前list
中xx最大的元素,XX是我们定义的条件,可能为长度,可能是别的,我们拿长度举例。
若不使用maxBy
,实现如下
fun main() {
val list = listOf(“a”, “aba”, “aabb”, “a”)
var maxStr = “”
for (str in list) {
if (str.length > maxStr.length) {
maxStr = str;
}
}
println(maxStr)
}
maxByOrNull
是一个普通方法,需要一个Lambda
参数,下面结合Lambda
使用maxByOrNull
fun main() {
val list = listOf(“a”, “aba”, “aabb”, “a”)
var lambda = {str: String -> str.length}
var maxStr = list.maxByOrNull(lambda)
println(maxStr)
}
直接当成参数也可传递
var maxStr = list.maxByOrNull({str: String -> str.length})
若Lambda
为方法的最后一个参数,则可将{}
提到外面
var maxStr = list.maxByOrNull() {str: String -> str.length}
若有且仅有一个参数且是Lambda
,则可去掉()
var maxStr = list.maxByOrNull {str: String -> str.length}
Kotlin
拥有出色的类型推导机制,Lambda
参数过多时可省略参数类型
var maxStr = list.maxByOrNull {str -> str.length}
若Lambda
只有一个参数,则可用it
替代参数名
var maxStr = list.maxByOrNull {it.length}
集合还有许多此类函数
创建list,后续操作都由此list
转换
val list = listOf(“a”, “aba”, “aabb”, “a”)
map
映射,返回新集合,将集合中的元素映射成另一个值
val newList = list.map { it.toUpperCase() }//将集合中的元素都准换成大写
filter
过滤,返回新集合,将集合中的元素进行筛选
val newList = list.filter { it.length > 3 }//筛选出长度大于3的元素
any
返回Boolean
,集合中是否存在元素满足Lambda
的条件,有则返回true
,无则false
val isAny = list.any {it.length > 10} //返回false
all
返回Boolean
,集合中元素是否全部满足满足Lambda
的条件,有则返回true
,无则false
val isAll = list.all {it.length > 0} //返回true
Lambda
的简单使用到这就结束了
Java函数式API的使用
Kotlin
调用Java
方法,若该方法接收一个Java
单抽象方法接口参数,则可使用函数式API
。Java
单抽象方法接口指的是接口只声明一个方法,若有多个方法则无法使用函数式API
。
Java
单抽象方法接口例如Runnable
public interface Runnable {
void run();
}
在Java
中启动一个线程如下:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(“test”);
}
}).start();
Kotlin
启动线程如下:
Kotlin
摒弃了new
,若想声明匿名内部类必须使用object
Thread(object : Runnable {
override fun run() {
println(“test”)
}
}).start()
因Runnable
是Java
单抽象方法接口,可对代码进行简化
Thread(Runnable {
println(“test”)
}).start()
Runnable
接口只用一个方法,使用Lambda
也不会有歧义,Kotlin
知道此Lambda
一定实现的为run
函数,借用Lambda
进一步简化:
Thread({
println(“test”)
}).start()
又因Thread
只需一个参数Runnable
参数,则可省略()
Thread {
println(“test”)
}.start()
与上类似的,click
也使用上述方法
button.setOnClickListener { println(“test”) }
这种方式可极大缩减代码量
空指针检查机制
国外统计程序出现最多的异常为空指针异常,Kotlin
存在编译时检查系统帮助我们发现空指针异常。
查看下面Java
代码
public void doStudy(Study study) {
study.doHomework();
study.readBooks();
}
上述代码时存在空指针风险的,传入null,则程序崩溃,对其进行改进
public void doStudy(Study study) {
if (study != null) {
study.doHomework();
study.readBooks();
}
}
对于Kotlin
来讲任何参数和变量不能为空
fun study(study: Study) {
study.doHomework()
study.readBooks()
}
fun main() {
study(null) //报错
study(Student()) //正确
}
Kotlin
把空指针异常的检查提前到了编译期,若空指针则编译期就会崩溃,避免在运行期出现问题
若我们有特殊的需求可能需要传递null参数,参数则按照下面声明
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
Runnable
接口只用一个方法,使用Lambda
也不会有歧义,Kotlin
知道此Lambda
一定实现的为run
函数,借用Lambda
进一步简化:
Thread({
println(“test”)
}).start()
又因Thread
只需一个参数Runnable
参数,则可省略()
Thread {
println(“test”)
}.start()
与上类似的,click
也使用上述方法
button.setOnClickListener { println(“test”) }
这种方式可极大缩减代码量
空指针检查机制
国外统计程序出现最多的异常为空指针异常,Kotlin
存在编译时检查系统帮助我们发现空指针异常。
查看下面Java
代码
public void doStudy(Study study) {
study.doHomework();
study.readBooks();
}
上述代码时存在空指针风险的,传入null,则程序崩溃,对其进行改进
public void doStudy(Study study) {
if (study != null) {
study.doHomework();
study.readBooks();
}
}
对于Kotlin
来讲任何参数和变量不能为空
fun study(study: Study) {
study.doHomework()
study.readBooks()
}
fun main() {
study(null) //报错
study(Student()) //正确
}
Kotlin
把空指针异常的检查提前到了编译期,若空指针则编译期就会崩溃,避免在运行期出现问题
若我们有特殊的需求可能需要传递null参数,参数则按照下面声明
[外链图片转存中…(img-Z78073F2-1715311726490)]
[外链图片转存中…(img-ZDJuivl9-1715311726491)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!