本篇文章来自郭霖大佬的第一行代码中的Kotlin教程,笔者只是在学习Kotlin过程中记录学习过程。
Kotlin系列已更新:
Kotlin基础学习-入门篇
Kotlin基础学习-第二篇
Kotlin进阶学习-第三篇
Kotlin进阶学习-第四篇
Kotlin进阶学习-第五篇
文章目录 kotlin的历史Kotlin的工作原理语言类型编译型解释型 Java的语言类型Kotlin的运行原理 创建Kotlin项目语法变量变量的声明基本类型var和val的本质区别 函数函数的声明声明技巧函数的调用 if语句ifwhen 循环语句类和对象类的创建和对象的初始化继承构造主构造次构造无主构造 接口接口的定义接口的继承 权限修饰符数据类和单例类数据类单例类 Lambda集合的创建和遍历ListSetMap Lambda的使用 Java函数式API的使用空指针检查机制判空辅助工具?.?:!! let函数全局判空注意事项 内嵌表达式函数的参数默认值 kotlin的历史Kotlin由JetBrains公司开发设计,2011年公布第一版,2012年开源。
2016年发布1.0正式版,并且JetBrains在IDEA加入对Kotlin的支持,安卓自此又有新的选择。
2019年谷歌宣布Kotlin成为安卓第一开发语言,安卓程序员由java转Kotlin已经迫在眉睫。
Kotlin的工作原理语言分为解释型和编译型两种
语言类型 编译型编译器直接将源代码一次性编译成二进制文件,计算机可直接执行,例如C,C++。
优点:一次编译,即可运行,运行期不需要编译,运行效率高。
缺点:不同操作系统需要不同的机器码,且修改代码需要真个模块重新编译
解释型程序运行时,解释器会将源码一行一行实时解析成二进制再执行。例如JS,Python。
优点:平台兼容性好,安装对应的虚拟机即可运行。
缺点:运行时需要解释执行,效率较低。
Java的语言类型java准确来说属于混合型语言,但更偏向于解释型。
编译:java存在JIT和AOT,JIT即时编译将可将热点代码直接编译成机器码,AOT预先编译可再安装时把代码编译成机器码
解释:java运行时需编译成class文件,java虚拟机再解释执行.class。
Kotlin的运行原理java虚拟机只认class文件, 虚拟机不会关心class时java文件编译来的,还是其他文件编译来的。那此时我们创造一套自己的语法规则,再做一个对应的编译器,,则可让我们的语言跑在java虚拟机上。Kotlin则是此原理,运行前会先编译成class,再供java虚拟机运行。
创建Kotlin项目打开android studio,在选择语言时,选择Kotlin
在包下创建kotlin文件
创建File命名为HelloWorld
敲入下面代码则可运行打印Hello World!
package com.hbsd.demo fun main() { println("Hello World!") }运行结果如下:
下面进入语法学习
语法 变量 变量的声明Kotlin使用var,val来声明变量,注意:Kotlin不再需要;来结尾
var 可变变量,对应java的非final变量
var b = 1val不可变变量,对应java的final变量
val a = 1两种变量并未声明类型,这是因为Kotlin存在类型推导机制,上述的a,b会默认为Int。假设想声明具体类型,则需下面的方式
var c: Int = 1 基本类型Kotlin不再存在基本类型,将全部使用对象类型
打开Kotlin对应的Java文件
再点击下方按钮
则可查看对应的Java文件
public final class HelloWorldKt { private static final int a = 1; private static int b = 2; private static int c = 10; ... }发现val a对应的为final,var b和var c 对应的为非final
Kotlin此设计的原因则是防止非final的滥用,若一个变量永远不被修改则有必要给其加上final,使其他人看代码时更好理解。
后期我们写代码时则可先使用val,若真的需要修改再改为var
函数 函数的声明无参无返回值
fun test() { }有参有返回值
参数的类型需要写在形参名后面中间使用:连接多个参数使用,分割",“返回值使用”:"拼接
fun add(a: Int, b: Int): Int { return a + b } 声明技巧当函数体只有一行代码时可直接使用下面方式声明方法
fun add (a: Int, b: Int): Int = a + bKotlin存在类型推导,返回值类型也可省略
fun add (a: Int, b: Int) = a + b 函数的调用 fun main() { test() println(add(1, 2)) } //运行结果 //test //3 if语句Kotlin中的选择控制有两种方式。if和when
if与Java的if区别不大,实现一个返回最大值的函数
fun max(a: Int, b: Int): Int { if (a > b) return a else return b }Kotlin的if可以包含返回值,if语句的最后一行会作为返回值返回
fun max(a: Int, b: Int): Int { return if (a > b) a else b }上述我们说过一行代码可省略返回值
fun max(a: Int, b: Int) = if (a > b) a else b查看对应的Java文件,其上述实现都与下面代码等价
public static final int max(int a, int b) { return a > b ? a : b; } when实现一个查询成绩的函数,用户传入名字,返回成绩级别
if实现
Kotlin的if语句必须要有else,不然会报错
fun getScore(name: String) = if (name == "Tom") "不及格" else if (name == "Jim") "及格" else if (name == "Pony") "良好" else if (name == "Tony") "优秀" else "名字非法"Kotlin中==等价于Java的equals比较的时是对象里的内容, === 等价于Java的==,比较的为对象的引用。
when实现
也必须实现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的不同如下表所示:
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); } // $FF: synthetic method public static UserBean copy$default(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<Int>() list.add(1) list.add(2) list.add(3) //listOf不可变,后续不可添加删除,只能查 val list1 = listOf<Int>(1, 2, 3 ,4 ,5) list1.add(6)//报错 //mutableListOf,后续可添加删除 val list2 = mutableListOf<Int>(1, 2, 3 ,4 ,5) list2.add(6) //循环 for (value in list2) { println(value) } } Setset用法与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<String>("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<String>("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<String>("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} //返回falseall返回Boolean,集合中元素是否全部满足满足Lambda的条件,有则返回true,无则false
val isAll = list.all {it.length > 0} //返回trueLambda的简单使用到这就结束了
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参数,参数则按照下面声明
fun study(study: Study?) { study.doHomework() //报错 study.readBooks() //报错 }?的意思则是当前参数可为空,如果可为空的话,则此对象调用的方法必须要保证对象不为空,上面代码没有保证,则报错,修改如下
fun study(study: Study?) { if (study != null) { study.doHomework() study.readBooks() } }也可借助判空辅助工具
判空辅助工具 ?.其含义是?前面对象不为空才执行.后面的方法
fun study(study: Study?) { study?.doHomework() study?.readBooks() } ?:其含义是?前不为空则返回问号前的值,为空则返回:后的值
比如
val c = if (a !=null ) { a } else { b }借助?:则可简化为
val c = a ?: b再比如
fun getTextLength(text: String?): Int { if (text != null) { return text.length } return 0 }借助?: 则可简化为
fun getTextLength(text: String?) = text?.length ?: 0 !!有些时候我们想要强行通过编译,就需要依靠!!,这时就是程序员来保证安全
fun study(study: Study?) { //假设此时为空抛出异常,则和java一样 study!!.doHomework() study!!.readBooks() } let函数let不是关键字,而是一个函数,提供了函数式API的编程接口,会将调用者作为参数传递到Lambda表达式,调用之后会立马执行Lambda表达式的逻辑
obj.let { it -> //it就是obj //编写操作 }比如上面函数
fun study(study: Study?) { study.doHomework() //报错 study.readBooks() //报错 }借助let则可改为
fun study(study: Study?) { //此时靠?.则保证了study肯定不为空,才会执行let函数 study?.let { //it为study it.doHomework() it.readBooks() } } 全局判空注意事项 //全局变量 var study: Study? = null fun study() { //报错 if (study != null) { study.readBooks() study.doHomework() } }因全局变量随时有可能被其他线程修改,即使判空处理也不能保证其没有空指针风险,而let则可规避上述问题
var study: Study? = null fun study() { study?.let { it.doHomework() it.readBooks() } } 内嵌表达式之前我们拼接字符串都是下面这样
var name = "zjm" var age = 20 println("My name is " + name + ". I am " + age + ".") //打印结果 //My name is zjm. I am 20.现在靠着Kotlin提供的内嵌表达式则不需要拼接,只需要下面这样则可实现
var name = "zjm" var age = 20 println("My name is $name. I am $age." ) //打印结果 //My name is zjm. I am 20.内嵌表达式还支持复杂的操作
${程序员想要的操作}
var name = "zjm" var age = 20 println("My name is ${if (1 < 2) "zjm" else "ljn"}. I am $age." ) //打印结果 //My name is zjm. I am 20. 函数的参数默认值Kotlin支持函数存在默认值,使用如下
fun main() { myPrint(1) myPrint(1, "lalala") } fun myPrint(value: Int, str: String = "hello") { println("num is $value, str is $str") } //结果如下 //num is 1, str is hello //num is 1, str is lalala若value想为默认值,则会报错,因为在使用时传入的第一个参数他认为是int的,传入字符串会类型不匹配
fun main() { myPrint("zjm")//报错 } fun myPrint(value: Int = 100, str: String) { println("num is $value, str is $str") }Kotlin提供了一种键值对传参来解决上述问题
fun main() { myPrint(str = "zjm") //正确调用 } fun myPrint(value: Int = 100, str: String) { println("num is $value, str is $str") }回顾之前的主次构造,Student如下
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) { } ... }上述的此构造借助参数默认值技巧是可以不写的,将第四个参数默认值为0 即可
class Student(name: String, age: Int, val number: String, val grade: Int = 0) : Person(name, age){ ... }上述关于Kotlin的使用,已经够日常开发需要,后续笔者会更新一些进阶使用
? 原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下 👍 点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力! ?? 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向! ?? 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。 |
标签: #kotlin入门