目录
在线运行Kotlin代码网址
helloworld
fun main() {
println("Hello, world!!!")
}
变量与函数
使用val关键字声明不可变变量,使用var关键字声明可变变量
fun main() {
val a:Int=10
println("a="+a)
var b:Int=10
b=b+10
println("b="+b)
}
显式声明变量
val a:Int=10
Java数据类型vsKotlin数据类型
函数
格式:
fun methodName(param1:Int,param2:Int):Int{
return 0
}
若函数无返回值
fun methodName(param1:Int,param2:Int):{
return 0
}
Kotlin语法糖
函数一行流
注:Android Studio自动导包
import kotlin.math.max
fun largerNumber(num1:Int,num2:Int)=max(num1,num2)
if条件语句
可以有返回值
fun largerNumber(num1:Int,num2:Int):Int{
val value=if(num1>num2){
num1
}else{
num2
}
return value
}
等效于
fun largerNumber(num1:Int,num2:Int):Int{
var value=0
if(num1>num2){
value=num1
}else{
value=num2
}
return value
}
进一步化简
fun largerNumber(num1:Int,num2:Int):Int{
return if(num1>num2){
num1
}else{
num2
}
}
使用语法糖
fun largerNumber(num1:Int,num2:Int)=if(num1>num2){
num1
}else{
num2
}
when条件语句
与switch类似
fun getScore(name:String)=when(name){
"Tom"->86
"Jim"->77
"Jack"->95
"Lily"->100
else->0
}
等效于
fun getScore(name:String)=if(name=="Tom"){
86
}else if(name=="Jim"){
77
}else if(name=="Jack"){
95
}else if(name=="Lily"){
100
}else{
0
}
当你的执行逻辑只有一行代码时,{}可以省略
可作类型匹配
fun checkNumber(num:Number){
when(num){
is Int->println("number is Int")
is Double->println("number is Double")
else ->println("number not support")
}
}
fun main() {
val num=10L
checkNumber(num)
}
如果不在when语句中传入参数
fun getScore(name:String)=when{
name=="Tom"->86
name=="Jim"->77
name=="Jack"->95
name=="Lily"->100
else->0
}
有些场景必须使用这种写法才能实现
fun getScore(name:String)=when{
name.startsWith("Tom")->86
name=="Jim"->77
name=="Jack"->95
name=="Lily"->100
else->0
}
循环语句
while循环和Java、C++或其他任何主流编程语言的用法基本相同,for循环会有差别。以下讨论for循环:
0..10表示[0,10]
fun main() {
val range=0..10
for(i in range){
println(i)
}
}
0 until 10,表示[0,10)
step 2,每次执行循环在区间范围内递增2
10 downTo 1,[10,1]降序区间
fun main() {
for (i in 0 until 10 step 2){
println(i)
}
for (i in 10 downTo 1){
println(i)
}
}
类与对象
class Person{
var name=""
var age=0
fun eat(){
println(name+" is eating. He is "+age+" years old.")
}
}
fun main() {
val p=Person()
p.name="Jack"
p.age=19
p.eat()
}
继承
两件事:
一、在父类前加open关键字,使其允许被继承
二、让子类继承父类,使用:作为继承关键字
open class Person{
var name=""
var age=0
fun eat(){
println(name+" is eating. He is "+age+" years old.")
}
}
class Student:Person(){
var sno=""
var grade=0
}
fun main() {
val p=Student()
p.name="Jack"
p.age=19
p.eat()
}
构造
主构造就是初始化,在初始化类的时候传入参数。如果想对传入的参数进行操作,可用init结构体。
open class Person(){
var name=""
var age=0
}
class Student(val sno:String,val grade:Int):Person(){
init{
println("sno is "+sno)
println("grade is "+grade)
}
}
fun main() {
val p=Student("a123",5)
}
Person类后面的空括号表示要去调用Person类中无参的构造函数。如果Person类具有主构造函数,则Person类没有无参构造函数,那么则Student类必须调用Person类的主构造函数,写法如下:
open class Person(val name:String,val age:Int){
}
class Student(val sno:String,val grade:Int,name:String,age:Int):
Person(name,age){
}
fun main() {
val p=Student("a123",5,"Jack",19)
}
次构造:
class Student(val sno:String,val grade:Int,name:String,age:Int):
Person(name,age){
constructor(name:String,age:Int):this("",0,name,age){
}
constructor():this("",0){
}
}
fun main() {
val student1=Student()
val student2=Student("Jack",19)
val student3=Student("a123",5,"Jack",19)
}
类中只有次构造函数,没有主构造函数,无需调用Person的无参构造函数,所以继承Person类的时候不需要加括号。
open class Person(val name:String,val age:Int){
}
class Student:Person{
constructor(name:String,age:Int):super(name,age){
}
}
fun main() {
val student1=Student("Jack",19)
}
接口
Kotlin 的接口可以既包含抽象方法的声明也包含实现。与抽象类不同的是,接口无法保存状态。它可以有属性但必须声明为抽象或提供访问器实现。
interface Study{
fun readBooks()
fun doHomework()
}
class Student(name:String,age:Int):Person(name,age),Study{
override fun readBooks(){
println(name+" is reading.")
}
override fun doHomework(){
println(name+" is doing homework.")
}
}
open class Person(val name:String,val age:Int){
}
fun main() {
val student=Student("Jack",19)
doStudy(student)
}
fun doStudy(study:Study){
study.readBooks()
study.doHomework()
}
在Study接口中doHomework()函数中加结构体,为默认实现,即删除在Student类中doHomework函数后,调用此函数会运行接口内定义的实现。
interface Study{
fun readBooks()
fun doHomework(){
println("do homework default implementation.")
}
}
class Student(name:String,age:Int):Person(name,age),Study{
override fun readBooks(){
println(name+" is reading.")
}
}
open class Person(val name:String,val age:Int){
}
fun main() {
val student=Student("Jack",19)
doStudy(student)
}
fun doStudy(study:Study){
study.readBooks()
study.doHomework()
}
函数的可见性修饰符
数据类
data class Cellphone(val brand:String,val price:Double)
测试
fun main() {
val cellphone1=Cellphone("Samsung",1299.99)
val cellphone2=Cellphone("Samsung",1299.99)
println(cellphone1)
println("cellphone 1 equals cellphone2 "+(cellphone1==cellphone2))
}
单例类
如果希望某个类在全局最多拥有一个实例,使用单例模式。Kotlin特有的单例类,具有单例模式。
object Singleton{
fun singletonTest(){
println("singletonTest is called.")
}
}
fun main() {
Singleton.singletonTest()
}
List、set、map
list是有序集合。set是无序集合。map就是map集合。初始化方法:
fun main() {
val list1=ArrayList<String>()
list1.add("Apple")
list1.add("Banna")
val list2=listOf("Apple","Banna")
val list3=mutableListOf("Apple","Banna")
list3.add("Watermelon")
val set1 =setOf("Apple","Banna")
val set2=mutableSetOf("Apple","Banna")
set2.add("Watermelon")
val map1=HashMap<String,Int>()
map1.put("Apple",1)
map1["Banana"]=2
val map2=mapOf("Apple" to 1,"Banana" to 2)
for (fruit in set2){
println(fruit)
}
for ((fruit,number) in map2){
println("fruit is "+fruit+" ,number is "+number)
}
}
lambda表达式
在水果集合中找到单词最长的水果
fun main() {
val list=listOf("Apple","Banana")
var maxLengthFruit=""
for (fruit in list){
if(fruit.length>maxLengthFruit.length){
maxLengthFruit=fruit
}
}
println("max length fruit is "+maxLengthFruit)
}
lambda表达式语法结构:
{参数名1:参数类型,参数名2:参数类型 -> 结构体}
var maxLengthFruit=list.maxBy({fruit:String->fruit.length})
当Lambda参数是函数最后一个参数时可:
var maxLengthFruit=list.maxBy()it:String->fruit.length}
当Lambda参数是函数唯一一个参数:
var maxLengthFruit=list.maxBy{fruit:String->fruit.length}
不声明参数类型:
var maxLengthFruit=list.maxBy{fruit->fruit.length}
当Lambda表达式的参数列表中只有一个参数时,也不必声明参数名,可以使用it关键字来代替:
var maxLengthFruit=list.maxBy{it.length}
举例:若希望所有的水果名都变成大写模式:
fun main() {
val list=listOf("Apple","Banana")
val newList=list.map{it.toUpperCase()}
for (fruit in newList){
println(fruit)
}
}
filter函数
val newList=list.filter{it.length<=5}.map{it.toUpperCase()}
any和all
any:存在一个满足条件为真
all:所有的都满足条件为真
fun main() {
val list=listOf("Apple","Banana")
val anyResult=list.any{it.length<=5}
val allResult=list.all{it.length<=5}
println("anyResult is "+anyResult+" , allResult is "+allResult)
}
可空类型
String不可空,String?可空,其他类可类推。
防空指针异常
fun doStudy(study:Study?){
if(study!=null){
study.readBooks()
study.doHomework()
}
}
判空辅助工具
?.操作符
if(study!=null){
a.doSomething()
}
等效于
a?.doSomething()
则doStudy()可改写为
fun doStudy(study:Study?){
study?.readBooks()
study?.doHomework()
}
?:操作符
val c=a?:b
非空断言工具:在对象后面加上!!
let函数:
.?操作符表示对象为空时什么都不做,对象不为空就调用let函数
fun doStudy(study:Study?){
study?.let{stu->
stu.readBooks()
stu.doHomework()
}
}
用it关键字化简
fun doStudy(study:Study?){
study?.let{
it.readBooks()
it.doHomework()
}
}
let函数可以处理全局变量的判空问题,if不行。
字符串内嵌表达式
"hello,${obj.name}.nice to meet you!"
当表达式中仅有一个变量
"hello,$name. nice to meet you!"
例
fun main() {
var brand="Samsung"
var price=1299.99
println("Cellphone(brand=$brand,price=$price)")
}
函数的参数默认值
fun printParams(num:Int,str:String="hello"){
println("num is $num, str is $str")
}
fun main() {
printParams(123)
}
通过键值对传参
fun printParams(str:String="hello",num:Int){
println("num is $num, str is $str")
}
fun main() {
printParams(num=123)
}
替代构造函数作用
class Student(val sno:String="",val grade:Int=0,name:String="",age:Int=0):
Person(name,age){
}