0.环境准备

用到是IDEA免费版本。新建一个Kotlin项目。

取个名字。

最后新建一个.kt文件,就可以开始使用kotlin了。

选择创建File。之后就会生成一个.kt的文件。

HelloWorld程序:

fun main() {var str:String="Hello"println(str)
}

手动编译运行:
执行下面的代码会生成一个叫HelloKt.class的字节码文件,非常奇怪的是,命令行并没有提供什么参数来修改这个生成的文件名字。

kotlinc Hello.kt

通过kotlin命令行来执行字节码文件:

kotlin HelloKt.class

也可以通过下面的代码生成jar文件,然后通过java -jar来运行

kotlinc Hello.kt -d hello.jar
java -jar hello.jar

1.数据类型

1.1数据的声明

下面的代码声明了一个String类型的变量,通过var关键字来声明变量,和java相比,这个写法好像非常的麻烦,多了var关键字还多了冒号,而且写的顺序也不一样,类型声明在后面,据说这个语法是从TypeScript那里学过来的,对TypeScript(JS)不熟。既然设计成这样,一定是有他的好处的。实际上,类型可以省略,kotlin会自动帮我们推导出来。

fun main() {var str:String="Hello"println(str)
}

省略后的写法:
也就是不管什么类型,都可以声明为var类型。对于开发者来说,还是节省了一点时间的,虽然牺牲了一点效率,因为倒推类型肯定需要额外的内部操作。

fun main() {var str="Hello"println(str)
}

1.2只读变量

下面的代码声明了一个String类型的变量,但是编译器会给一个警告,说"Hello"是一个只读变量,可以用val声明。注意是最后一个字母是L而不是R,var和val是两个关键字。var可以用来声明一般的变量,val用来声明只读变量,类似于java的final关键字。

 var str="Hello"

用val声明:

 val str="Hello"

注意这个只读并不等于常量,常量是用另一个关键字const来修饰的。

1.3 const常量

常量只能声明在方法外部,在方法内部是不能声明常量的。

const val MAX=1024fun main() {println(MAX)
}

在kotlin中,const相对于java的static final。我们可以通过双击shitf,输入kotlin bytecode查看字节码信息。

public final static I MAX = 1024

1.4 引用类型

我们知道Java有引用类型和基本数据类型这两种类型。引用类型放在堆里面,一般是java对象。而kotlin只有一种类型,也就是引用类型,但是在编译的时候,还是会转化为基本类型。

val age=10

在字节码里面的LOCALVARIABLE I代表int类型。也就是会转化为基本数据类型。字节码内容了解一下就行。

LOCALVARIABLE age I L1 L6 0

2. 表达式

2.1 if else表达式

和Java的用法一样,就不写了。

2.2 range表达式

字面意思就是范围表达式,用到的关键字是in。下面这个例子很好的说明了使用的in关键字的用法。不光可以指定数字,还可以指定数组或者集合。

    val score=66if (score in 0..60){println("bad")}else if (score in 61..80){println("not bad")}else{println("good")}

2.3 when表达式

相对于Java的switch表达式,但更加简洁,推荐将所有的if else表达式都转化成when的形式,when表达式在kotlin中是非常常用的。
下面的代码对比Java的switch语句少了case和default关键字看起来简洁了非常多。
而且可以返回多种数据类型,这里返回了String类型的“男”,“女”,和int类型的-1。
返回类似是Any类型,这个有点类似Java的Object类型。->实际上是一个lambda表达式。如果只有单行可以直接返回结果,不用写return;

    val gender=3;val result:Any=when(gender){1->"男"2->"女"else-> -1}println(result)

如果lambda表达式存在多行,那么需要加一个大括号{}。

    val gender=3;val result=when(gender){1->"男"2->"女"else-> {println("未知")println("程序退出")}}println(result)

程序最后输出如下,kotlin.Unit类似于Java的void,因为println并没有返回值。

未知
程序退出
kotlin.Unit

2.4 String模板

String模板就是String的拼接。在Java中,我们用++拼接字符串,这个实际上是非常麻烦的。很多语言都支持用符号拼接内容,用符号拼接内容,用符号拼接内容,用{}拼接表达式。

用$拼接内容:

 val animal="dog"val color="yellow"println("The $animal's color is $color")

输出内容:

The dog's color is yellow

用${}拼接表达式:

    val animal="dog"val color="yellow"val age=10println("The $animal's is $color and ${if(age>5) "old" else "young"}")

输出内容:

The dog's is yellow and old

3.函数

3.1 函数头

kotlin的函数头和Java还是差别非常大的,priavate表示权限,默认是oublic,fun是函数声明关键字,括号里面是参数列表,最后的:Boolean表示返回类型。
可以看到参数列表和返回值的顺序和Java是相反的,这实际上是更加符合逻辑的,先传输入再确定输出类型,也就是输入输出。只是Java用习惯了,也就习以为常了。

private fun doSomething(i:Int ,s:String):String{return "resultCode";
}

函数调用
直接调用就可以,不需要创建对象。

fun main() {val flag = doSomething(5, "abc")println(flag)
}

3.2 参数的默认值

参数还可以给默认值,只是Java所没有的,Java有固定的默认值。kotlin支持指定默认值。

private fun doSomething2(a:Int=2,s:String="null"):String{return "$a $s";
}fun main() {//没有传任何参数val result = doSomething2()println(result)
}

输出结果:

2 null

3.3 具名函数参数

具名的意思就是在传入参数的时候可以指定参数的名字,这样的目的是增加可读性,因为光传参数,不知道这个参数是干嘛用的,可能传错位置,可读性也很差。
例如下面的代码,代码一的位置,写了参数的名字是age,和name,这样就不会搞错参数位置了,可读性非常强。但是,IDEA是支持参数类型提示的,可以直接显示参数类型,这相对于是IDEA已经实现的功能,可能就是为了弥补Java没有这个功能而设计的。

fun main() {//代码一var flag=doSomething(age=5,name="abc")
}private fun doSomething(age:Int,name:String):Boolean{return true;
}

3.4 Unit函数

在Java中没有返回类型就返回void类型,但在泛型的时候,这个概念就有点矛盾。kotlin用kotlin.Unit这个类型表示没有返回类型。在kotlin中,如果没有返回类型,那么函数的返回类型可以不用写任何类型,也不用写void,kotlin根本就没有void这个关键字。

fun main() {println(testUnit(5,"abc"))
}private fun testUnit(age:Int,name:String) {}

输出:

kotlin.Unit

3.5 反引号的函数名

在函数名上面加一个反引号,kotlin支持这种写法,这样做的主要目的是为了和Java的交互性。Java和Kotlin是可以无缝调用的,但因为Java和Kotlin的关键字不同,可能一些方法名在Java是合法的,但到了Kotlin就变成非法,这时候就可以加反引号解决。
例如下面的Java代码,声明了一个is方法,这在Java里面是合法的,但如果在kotlin里面要调用这个方法就不行了,因为is在Kotlin里面是一个关键字。

public class Data {public static void is(){}
}

这时候在函数名上加一个反引号就可以解决这个问题。这样is就不被当作是关键字而可以在kotlin里面使用了。

//在kotlin中调用
Data.`is`()

有趣的是,加了反引号之后,方法名甚至可以写空格例如下面的代码。

private fun `first we calculate add`(a: Int,b:Int):Int{return a+b;
}private fun `second we calculate sub`(a: Int,b:Int):Int{return a-b;
}fun main() {val add= `first we calculate add`(1,2)val sub = `second we calculate sub`(1, 2)println("$add $sub")
}

用自然语言编程不再是梦。当然这个应该是用不太上,主要还是为了解决和Java的交换问题,写类似注释的方法名还是交给注释比较好。

3.6匿名内部类

我们举String的count方法为例,count方法有两个重载,第一个无参函数非常好理解,第二个重载声明如下,要求我们传入一个lambda表达式,这个表达式传入char,返回boolean(判断条件),最后整个函数返回一个int,也就是我们指定的char字符有多少个。

public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int
    var count="Kotlining".count()var countI = "Kotlining".count({letter -> letter == 'i'} )println(count)println(countI)

输出

9
2

3.7 函数类型

这个和C语言的函数指针是非常像似的,但java是移除了这些特性的。
我们看下面的代码,第一次看这个代码可能非常的奇怪,看着像lambda表达式,又不完全是,其实这里的关键就是理解()->String的含义。这个语法是lambda表达式,但这里的真正含义是匿名内部类类型,并且这个匿名内部类返回String类型。顺理成章的,我们定义的变量result的类型也就变成了String类型。注意是一个类型声明,而不是lambda表达式实体,lambda表达式的实体是{}里面的内容。

 var result:()->String={val animal="dog""This is $animal"}

看下和lambda表达式的对比:
下面是java的lambda表达式.一个非常明显的区别就是kotlin的匿名内部类没有return,而且在里面也是不可以写return的,这是因为他默认返回类型是表达式的最后一行。为了实现这个功能,就必须显示的声明类型,因为可能返回一个类对象。

 ()->{val animal="dog"return "This is $animal"}

当然也是可以带参数的。在()里面声明参数类型,在{}开头可以写具体名字。写法还是非常飘逸的。

 val result2:(String,Int)->String={name,age->val animal="dog""This is $animal , name is $name , age is $age"}println(result2("tom",5))

输出:

This is dog , name is tom , age is 5

还有一种类型推断的写法,如下,参数我们还是要指定类型的,但返回值可以推断出来。感觉这种写法更简洁一点,前面的写法更标准一些。

val result4 = { name: String, age: Int ->val animal = "dog""This is $animal , name is $name , age is $age"}

3.8 it关键字

接着上小节,如果参数只有一个的时候,我们可以不写具体的参数名字,kotlin默认为我们提供了一个it关键字,可以直接使用这个关键字当参数变量名称。

  val result3:(String)->String={val animal="dog""This is a $animal , name is $it."}println(result3("tom"))

输出:

This is a dog , name is tom.

3.9函数做为函数参数

下面这个函数的功能是显示学生信息,包括学生的姓名和身份证,第二个参数是一个函数类型,没错可以将一个函数做为参数传进来。这个函数可以合成学生的身份证,身份证由邮政编码,生日,编号构成。

private fun showStudentInfo(name: String, getId: (Int,Int,Int) -> String): String {//必须用大括号return "$name's id is ${getId(300027,20001212,1001)}"
}
 var getId = { code: Int, birth: Int, num: Int ->"$code$birth$num"}println(showStudentInfo("Tom", getId))

输出:

Tom's id is 300027200012121001

其实这个写法非常的奇怪。声明一个函数然后又去调用,那干嘛不直接写一个函数呢?其实,上面的写法是不合理的,一般不会这么写,问题就出在var getId这个变量上,我们写了这个变量来引用函数类型,这是没有必要的,因为我们用函数类型的目的就是为了写匿名函数,取名字完全是多此一举。可以简化写成下面的样子。

 println(showStudentInfo("Tom", { code, birth, num ->"$code$birth$num"}))

这样看起来就是非常简洁了。而且,kotlin有规定,如果只有一个函数类型,或者函数类型是最后一个,()可以省略。
函数类型是最后一个的情况:

  println(showStudentInfo("Tom") { code, birth, num ->"$code$birth$num"})

只有一个函数类型做参数的时候

   println(showStudentInfo { code, birth, num ->"$code$birth$num"})

这种写法一定要掌握,因为这个写法在kotlin里面是非常常见的。
这种写法一定要掌握,因为这个写法在kotlin里面是非常常见的。
这种写法一定要掌握,因为这个写法在kotlin里面是非常常见的。

3.10 内联函数

内联函数的主要用途就是为匿名函数提高性能。在调用下面的有函数类型做为参数的方法时,会使用到匿名内部类。第二个参数要求我们传入匿名内部类,对于编译器来说,匿名内部类的创建和普通类是一样的,但既然是匿名的,效率应该要更高写,如果也是和普通类一样创建,效率就比较低了。内联函数就是为了解决这个性能问题,那么是怎么解决的呢?答案是通过宏替换,如果你学过C语言,你就知道C语言的宏替换,内联函数也是一样的,通过宏替换,我们直接把匿名内部类的代码直接复制到调用的函数里面,这样就不需要创建类了,不需要创建类当然性能就提高了。

private fun showStudentInfo(name: String, getId: (Int,Int,Int) -> String): String {return xxx
}

使用方法就是直接添加一个inline关键字就可以了。

private inline fun showStudentInfo(name: String, getId: (Int,Int,Int) -> String): String {return xxx
}

3.11 函数引用

在调用含有函数类型的方法时,不光可以传入匿名内部类,也可以传通常的方法,这时候就需要用到函数引用。
例如下面的代码,foo方法的参数列表和showStudentInfo里面的getId函数类型的参数列表是一样的,这个时候可以把foo直接传给showStudentInfo。使用方法就是在::加普通函数名称。

private fun showStudentInfo( name:String, getId: (Int,Int,Int) -> String): String {//必须用大括号return   "$name's id is ${getId(300027,20001212,1001)}"
}private fun foo(  a:Int,b:Int,c:Int ): String {return   "$a$b$c"
}println(showStudentInfo("Tom", ::foo))

输出:

id is 300027200012121001

3.12 函数类型做为返回类型

简单来说,就是一个函数返回另一个函数。什么?这有什么意义?如果有多个函数进行嵌套调用,那么就会形成函数之间的层层包含关系。这样的好处就是子函数可以共享父函数的变量,这种写法在脚本语言中是非常常见的,例如JavaScript。这样做的原因是脚本语言存在一个很大的问题,就是即使在不同的文件里面定义相同的变量名也会报错。因为脚本语言并没有像java这样有package和class的概念。kotlin也可以做为脚本语言。我们只能举个简单的例子来说明一下她的形式,理解的比较深还是需要大量的实践的。
看下面的代码,返回值是一个函数类型,传入一个String返回String。

private fun foo(a:Int):(String)->String{return {"$it"}
}

在main函数中执行,返回函数类型的变量bar,可以调用,传入"abc"返回"abc"

    var bar = foo(1)println(bar.invoke("abc"))

输出:

abc

kotlin入门最容易教程一(最全,最详细)相关推荐

  1. 视频教程-Oracle数据库从入门到实用教程详解-Oracle

    Oracle数据库从入门到实用教程详解 全栈工程师,2010年从事软件开发以及软件教育培训工作,至今将近十余年,在项目的开发,设计,到管理上积累了丰富的实战经验,教学风格上通俗易懂,问题解答环节一对一 ...

  2. 阿里架构师开源《Kotlin入门教程指南》+《高级Kotlin强化实战》

    对于有Java基础的程序员来说,Kotlin是一门非常容易上手的编程语言,也是一门必须掌握的编程语言.Java代码在运行前需要编译生成一种特殊的class文件,然后Java虚拟机会识别并解释这些cla ...

  3. 关于 Kotlin 一系列的学习教程、文章。学好 Kotlin 从这里开始,争取做到最全、最详细。让没有编程经验的朋友也能通过这个系列教程用 Koltin 语言来开发项目

    KotlinLearn 项目地址:Jetictors/KotlinLearn 简介: 这是一个关于 Kotlin 一系列的学习教程.文章.学好 Kotlin 从这里开始,争取做到最全.最详细.让没有编 ...

  4. Kotlin入门教程——目录索引

    Kotlin是谷歌官方认可的Android开发语言,即将发布的Android Studio 3.0版本也会开始内置Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初And ...

  5. kotlin coroutines 协程教程-入门用法

    kotlin coroutines 协程教程-入门用法 Coroutine 协程,是kotlin 上的一个轻量级的线程库,对比 java 的 Executor,主要有以下特点: 更轻量级的 api 实 ...

  6. Kotlin入门(24)如何自定义视图

    Android提供了丰富多彩的视图与控件,已经能够满足大部分的业务需求,然而计划赶不上变化,总是有意料之外的情况需要特殊处理.比如PagerTabStrip无法在布局文件中指定文本大小和文本颜色,只能 ...

  7. Kotlin入门(8)空值的判断与处理

    上一篇文章介绍了如何对循环语句进行操作,末尾还演示了发现空串时直接继续下一循环,只是在初始化字符串数组时使用了"val poem2Array:Array<String?> = * ...

  8. vue设置cookie的domain无效_【Vue.js入门到实战教程】16Tailwind 与 Bootstrap 的区别和使用入门...

    来源 | https://xueyuanjun.com/post/22065我们知道,从 Laravel 8 开始,自带前端脚手架代码默认兼容 Tailwind CSS 框架,取代了之前的 Boots ...

  9. Kotlin入门(33)运用扩展属性

    进行App开发的时候,使用震动器要在AndroidManifest.xml中加上如下权限: <!-- 震动 --><uses-permission android:name=&quo ...

  10. Kotlin入门(32)网络接口访问

    手机上的资源毕竟有限,为了获取更丰富的信息,就得到辽阔的互联网大海上冲浪.对于App自身,也要经常与服务器交互,以便获取最新的数据显示到界面上.这个客户端与服务端之间的信息交互,基本使用HTTP协议进 ...

最新文章

  1. 在Ubuntu 14.04 64bit上安装Master PDF Editor 3.2.81
  2. 深度学习100例-卷积神经网络(CNN)彩色图片分类 | 第2天
  3. JZOJ 3815. 【NOIP2014模拟9.7】克卜勒
  4. DCMTK:修改DICOM文件的类
  5. 卡通渲染进阶 = toonlighting + outline + rimlighting + hair specular
  6. 学习vi和vim编辑器(8):全局替换(1)
  7. 基于SpringCloud实现Shard-Jdbc的分库分表模式,数据库扩容方案
  8. 华为鸿蒙系统耳机,华为鸿蒙系统真的来了,完整升级名单曝光!
  9. 在c语言中定义共用型数据类型的关键字是,C语言的关键字共有32个,根据关键字的作用,可分其为数据类型关键...
  10. Shell脚本学习-阶段十二-在CentOS 7上给一个网卡分配多个IP地址
  11. 【教程】如何正确的写一个Lemon/Cena的SPJ(special judge)
  12. Android6.0之前版本(AwesomePlayer)OMXCodec执行流程细节
  13. kali字典_Web渗透测试——暴力破解字典制作工具的使用2
  14. 手把手教你 如何安装 Ubuntu(乌班图)
  15. 结构体初始化、结构体指针、结构体数组
  16. cygwin 编译android,再次在 cygwin 下编译 Android toolchain
  17. [frida] 01_食用指南(持续更新)
  18. Trimmed 稳健均值估计与 中位数-中位数配对偏差法估计标准差——理论与 Python 实现
  19. 网站死链检查处理方法
  20. Layui form 表单验证lay-verify

热门文章

  1. 提醒:使用过期Win10预览版后果很严重
  2. 凤舞江湖手游如何用电脑玩 凤舞江湖PC电脑版玩法教程
  3. 介绍一些新手都能看的明白的基础破解教程
  4. iOS 下载和播放 M3U8
  5. 鸡兔同笼(C语言实现)
  6. python下stl格式转换off格式
  7. xmlspy2014下载安装(可用)
  8. html怎么设置用户登录界面设计,html怎么做用户登录界面设计步骤,登录界面设计这样做?...
  9. 什么是MIME类型?
  10. WinMTR 0.9.2 绿色免费版