赞
踩
Kotlin 是一门全栈语言
安装Kotlin插件,如图所示:
安装后要重启一次才能生效;
创建一个Kotlin工程,如图所示:
3. 根据实际,填写项目的groupId,ArtifactId,以及Version,如图所示:
一路默认下去即可,然后成功创建项目,然后在此项目中创建Kotlin包,如图所示:
紧接着创建包net.println.kotlin(根据实际来,此处可不一致),然后创建HelloWorld.kt,如图所示:
编写Hello,world代码如下:
fun main(args:Array<String>){
println("Hello World")
}
执行,如图所示:
执行成功后,控制台会打印Hello,world字样,说明运行成功,如图所示:
点击println进去,可以看到源码,其打印操作是调用的Java的System.out.println,如图所示:
简单来说就是看懂如图例子:
val aBoolean : Boolean = true
val anotherBoolean : Boolean = false
数字类型如下:
int,Long类型的最大值和最小值
// 2147483647
val maxInt: Int= Int.MAX_VALUE
// -2147483648
val mintInt: Int=Int.MIN_VALUE
val maxLong : Long=Long.MAX_VALUE
val minLong: Long=Long.MIN_VALUE
val aFolat: Float=20F
val maxFolat: Float=Float.MAX_VALUE
val minFolat: Float=- Float.MAX_VALUE
val maxShort : Short=Short.MAX_VALUE
val minShort : Short=Short.MIN_VALUE
val maxByte: Byte= Byte.MAX_VALUE
val minByte : Byte= Byte.MIN_VALUE
val后面的为变量名,可替换为实际名称;Long类型的长整形后面可以加个L; Float类型后面必须加F,f;Float是浮点类型,有精度问题,计算钱相关的不要用这个;
装箱和拆箱
特点:
Char类型转义字符如图:
不可隐式转换
比较相等
字符串模板
val arg1: Int =0
val arg2: Int =1
// java款式的加法
println(""+arg1+"+"arg2+"="+(arg1+arg2))
// kotlin款式的加法
println("$arg1+ $arg2=${arg1+arg2}")
// 如果要打印美元 $这个符号,则再加一个$
val salary: Int = 1000
println("$"+"$salary")
// 或者使用转义符号
println("\$salary")
// 三个引号,转义会失效,支持换行
val txt:String ="""
hello
,
world
"""
// 打印它的字符数量
println(rawString.length)
什么是类?
class<类名>{<成员>}
什么是对象?
类和对象的关系?
对象也经常被称作“类的对象”或者“类的实例”
类的继承
类与对象的实例图示:
如果在类中加了init字段,则在创建过程中会自动执行其中的方法,如图所示:
当构造只有一个的时候可以进行省略,如果有多个则不可以,如图所示:
子类继承了父类中的一些方法,如图所示:
Any是一切类的父类,它拥有equals,hashCode,toString方法,则说明在Kotlin中的其他所有类,都拥有这些方法,如图所示:
val sub: SubClass = parent as SubClass
这里的含义是,判断parent变量为SubClass的子类,若为其子类,则sub是SubClass类型,如不为则直接抛出异常;
- 安全类型转换
- val sub: SubClass? = parent as? SubClass
- 如果转换失败,返回null,不抛异常
> 如果parent不是SubClass的子类,则类型转换失败,sub不能编程SubClass类型,则sub的值为null;
package net.println.koltin.DemoTest
import net.println.kotlin.HelloWord as Hello
fun main(args:Array<String>){
val sayHello:Hello=Hello();
}
这里导入的Hello,就是HelloWorld类。通过创建Hello,就相当于创建了一个HelloWord,所以sayHello看似是对Hello实例化,实际上是对HelloWorld进行了实例化;
// 前后都闭区间 [0,1024]
val range:IntRange=0..1024
// 前闭后开的区间 [0,1024) = [0,1023]
val range_exclusive:IntRange= 0 until 1024
val empty_Range:IntRange=0..-1
fun main(args:Array<String>){
// true 是为空,因为此范围中没有值
println(emptyRange.isEmpty())
// true 此范围中包含了50
println(range.contains(50))
// true 检查50是否在range的范围中
println(50 in range)
}
// 下面打印出来的结果为: 0,1,2,3,4,5,6,7,8,9,10...
for(i in range_exclusive){
println("$i,")
}
用i in IntRange可以作范围判断,以及辅助遍历等操作
数组是什么?
An impressive display or range of a particular type of thing or an ordered arrangement,in particular
基本写法
基本操作:
为了避免不必要的装箱和拆箱,基本类型的数组是定制的,如图所示:
数组示例代码:
// 创建一个int数组
val arrayOfint: IntArray = intArrayOf(1,3,5,7)
// 创建一个Char数组
val arrayOfChar: CharArray = charArrayOf("H","e","l","o","W","o","r","l","d")
// 创建一个自定义对象数组,根据上面创建的类
val arrayOf书记: Array<市委书记> = arrayOf(市委书记("张"),市委书记("赵"),市委书记("黄"))
fun main(args: Array<String>){
// 打印 int数组
println(arrayOfInt.size)
for(int in arrayOfInt){
println(int)
}
}
println(arrayOf书记[1])
// 这里将方书记赋值给了数组的1 索引处。此处1索引原来的对象会变成新替换的对象,所以重新打印1索引处的书记会变成新的方书记;
arrayOf书记[1] = 市委书记("方")
println(arrayOf书记[1])
// 这里的joinToString("")表示每个字符之间不用什么连接。 传入制定参数就以指定值进行连接。如果不传,默认以,号连接,比如: H,e,l,l,o... 此处代码打印结果为: HelloWorld
println(arrayOfChar.joinToString(""))
什么是常量?
什么是变量:
类型推导- 编译器可以推导量的类型
var是可变量,val 是不可变,它是常量;
val虽然是不可变,但是它不是静态的,如果需要在编译期时就加在,可以在前面加一个const字段;
fun main(args: Array<String>){
println("Hello,world")
// 打印args数组的索引为1 的值
println(${args[0]})
if (args.size !=2){
}
}
如果没有传参,会报数组索引异常。这里main函数没有为args赋值;如果启动时,传入了参数就可以打印了;同时如果有返回值,则需要在main(…)这个括号后面加 :返回值类型来定义返回值类型;
fun main(args: Array<String>){
checkArgs(args)
val arg1=args[0].toInt()
val arg2=args[1].toInt()
println("$arg1+$arg2=${sum(arg1,arg2)}")
}
fun checkArgs(args: Array<String>){
if(args.size != 2){
println("请传入两个整形参数,例如 1, 2")
System.exit(-1)
}
}
fun sum(arg1: Int ,arg2:Int):Int{
return arg1+arg2
}
什么是lambda表达式?
{[参数列表]->[函数体,最后一行是返回值]}
val sum ={a:Int,b:Int-> a+b}
Lambda的类型表示举例:
// 无参,返回值为Unit
()->Unit
// 传入整型,返回一个整型
(Int)->Int
// 传入字符串、Lambda表达式,返回Boolean
(String,(String)->String)->Boolean
Lambda表达式的调用
val sum ={a:Int,b:Int->a+b}
sum(2,3)
sum.invoke(2,3)
Lambda表达式的简化
使用for 我们用foreach也可以进行遍历;
什么是类成员?
函数和方法的区别?
函数如何定义方法?
class Hello{
fun sayHello(name:String)=println("Hello,$name")
}
定义属性
class Hello(val aField:Int,notAField:Int){
val anotherFIeld:Float=3f
}
属性的访问规则:
val a:Int=0
get()=field
var b:Float=0f
set(value){field=value}
get(){return field} 其中field指代了此变量
属性初始化
class X
class A{
// 使用lateinit延迟初始化,不需要立即给值
lateinit var c: String
val e: X by lazy{
X()
}
}
中缀表达式
class Book{
infix fun on(place: String){
...
}
}
if(Book() on "My Desk"){...}
if 表达式
if(a==b)
...
else
...
在if表达式中,我们既可以用来做条件判断,也可以类似java三元运算符一样直接用来当一个值进行使用。比如
val b=2
// 当b等于2时,则a等于3 否则等于5
val a= if(b==2) 3 else 5
When 表达式
fun main(args: Array<String>){
val x=5
when(x){
is Int-> 逻辑代码...
in 1..100-> 逻辑代码...
!in 1..100-> 逻辑代码...
args[0].toInt()-> 逻辑代码...
}
}
这里的when处传入值,下面任意满足条件且按先后只执行第一个符合条件的代码逻辑;
var str="今天是周末;"
val biaodian = when {
str.contains(";") -> {
";"
}
str.contains(";") -> {
";"
}
str.contains(",") -> {
","
}
else -> {
","
}
含义可以参考此java代码:
var str="今天是周末;"
val biaodian = if (str.contains(";")){
";"
}else if (str.contains(";")){
";"
}else if (str.contains(",")){
","
}else{
","
}
for循环
for(element in elements)...
fun main(args: Array<String>){
// 遍历一
for(arg in args){
println(arg)
}
// 遍历二
for((index,value) in args.withIndex()){
println("$index-> $value")
}
// 遍历三
for(indexedValue in args.withIndex()){
println("${indexedValue.index} -> ${indexedValue.value}")
}
}
可网上找
While循环
fun main(args:Array<String>){
var x=5
while(x>0){
println(x)
x--
}
do {
println(x)
x--
}while(x>0)
}
跳过和终止循环
return try(
x/y
)catch(e:Exception){
0
}finally{
...
}
异常的捕获及处理与java类似,不过其可以作为值进行使用;
具名参数
fun sum(arg1:Int, arg2:Int)= arg1+arg2
sum (arg1=2 ,arg2=3)
变长参数
Spread Operator
默认参数:
代码示例:
fun main(vararg args: String){
var array= intArrayOf(1,3,4,5)
// string="Hello" 是一个默认参数
// *array表示将array数组展开,将一个个元素传入,如: hello(3.0,1,3,4,5,string="Hello")
hello(3.0,*array,string="Hello")
}
fun hello(double:Double, vararg ints:Int, string:String){
ints.forEach(::println)
println(string)
}
apply plugin:'application'
mainClassName="net.println.kotlin.chapter3.CalcKt"
然后gradle会下载一些相关插件,完成后会在Gradle的窗口中,在Tasks-> distribution-> InstallDist 中执行InstallDist. 如图所示:
面向对象的基本概念
类实例:
// 定义一个类
class Demo{
// 定义一个可读变量
val i=4
// 定义一个方法
fun out(i: int){
println(i)
}
}
// 定义一个接口
interface chouxianglei{
// 定义一个接口方法
fun hello()
}
继承一个接口的时候,使用类名(),实现一个接口的时候,使用类名即可,在Kotlin 中是单继承,多实现;如图所示:
什么是接口?
interface InputDevice{
fun input(event: Any)
}
接口与抽象类的区别:
继承(实现)语法要点
Class D: A(),B,C
class Manager(driver: Driver): Driver by driver
接口方法冲突
使用object类可以创建一个最简单的单例类
- 伴生对象的特点:
- 每个类可以对应一个伴生对象
- 伴生对象的成员全局独一份
- 伴生对象的成员类似Java的静态成员
> 伴生对象就相当于静态变量和静态方法的整体;
- 使用伴生对象需要注意的地方:
- 静态成员考虑用包级函数、变量替代
- @JvmField 和 @JvmStatic的使用
class Latitude private constructor(val value: Double){
companion object{
@JvmStatic
fun ofDouble(double:Double):Latitude{
return Latitude(double)
}
fun ofLatitude(latitude: Latitude): Latitude{
return Latitude(latitude.value)
}
@JvmField
val TAG: String="Latitude"
}
}
这里@JvmStatic和@JvmField不加此注解,在companion object代码块中均可作为静态方法或静态属性,但是如果不加不能被java代码所识别。如果涉及到java代码调用此静态方法或静态属性,则需要加@JvmStatic或@JvmField注解;它们分别修饰方法和属性;
方法重载的特点:
默认参数的特点:
重载与默认:
方法重载能够用默认参数来解决,所以能不使用就尽量不使用。@JvmOverloads能用于被java代码所识别,如果只在Kotlin中使用可以不用加这个注解;
// 添加方法:
fun X.y():Z{...}
// 添加属性
val X.m 注意扩展属性不能初始化,类似接口属性
如图所示,此懒加载就是一个代理:
特点:
val/var <property name>: <Type> by <expression>
实际上就是说,当我们使用了 val/var xxx by yyy()的属性代理时,其代码执行逻辑主要看yyy()了。如果是var方法我们需要实现setValue和getValue,如果是val则只需要实现getValue方法即可,因为val是可读常量;
代码示例:
其中定义了存值和赋值的get,setValue方法;当我们创建时则会自动执行setValue,当取值时则会调用getValue;
特点:
代码示例:
同时,我们可以直接在类中直接定义构造参数值,如图所示:
此时不需要传入构造参数,便可将构造参数值外传并执行其他操作,如打印,如图所示:
数据类有一个问题,就是它没有空的默认的构造方法。编译生成的类是一个final的且无空构造方法,所以不是JavaBean,在有些时候使用是有问题的。我们可以通过noarg和allopen插件解决:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200611225801792.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTI4MDQ5,size_16,color_FFFFFF,t_70)
特点:
匿名内部类:
定义一个内部类(非静态):
非静态内部类,需要在 类的class 前面加inner关键字
定义一个内部类(静态):
静态内部类。默认内部类为静态内部类;调用时,外部类.内部类()即可;静态内部类无法获取非静态的外部类的属性和方法,因为它是先被编译加载的;而非静态内部类可以持有外部类的非静态属性和方法;
当调用外部类的属性时,我们可以直接调用,也可以用this.@外部类名.属性或方法来执行,如图所示:
匿名内部类实现方法示例:
特点:
定义一个枚举类,如图所示:
$name 是它的名称 $ordinal 是它括号里的值
调用示例:
// 打印指定的枚举类 1,DEBUG
println(LogLevel.DEBUG.getTag())
// 打印指定枚举类的序号 1
println(LogLevel.DEBUG.ordinal)
// 打印指定枚举类的实例 ERROR,4
println(ERROR,4)
特点:
密封类代码示例:
使用枚举适用于没有参数的情况下,而使用密封类可以用在多参数的情况下,每个类的参数都不尽然相同,同时又想保护此类,不让其他fun方法返回此类,就可以使用密封类;
密封类在class前面加 sealed关键字
第一种方式 ::println 说明任何对象(Any)都可以调用此方法,所以才能这样写;
map: 一对一映射处理
flatMap: 最细化分离
joinToString(",") 字符串连接
taskWhile 符合条件立即结束,返回符合条件之前被校验的数据
.let 调用者不为空时,则执行后面的逻辑;
常见高阶函数
具体可百度详细学习
fun main(args: Array<String>){
val add5=add(5)
println(add5(2))
}
fun add(x: Int):(Int)->Int{
data class Person(val name:String,val age:Int)
return fun(y:Int):Int{
return x + y
}
}
fun makeFun():()->Unit{
var count=0
return fun(){
println(++count)
}
}
fun main(args: Array<String>){
val x=makeFun()
x()
x()
x()
...
}
概述:
代码图片示例:
这里是打印参数的例子;
概述:我们项目工程是以Gradle编写的,可以用Kotlin脚本编写;
好处:
一些区别:
改造前:
改名后,全部爆红:
重启之后,按照Kotlin写法改正后:(可以与原来代码比对,以学习kotlin脚本语法)
改写之后能够正常编译、打包、运行操作,与之前一样;
什么是协程
协程的特点:
协程要解决什么问题
如何支持协程
本章目标
这里的圈可能会转很多次,取决于调用多少次suspend函数;
上面这两个都是加上之后与java的静态变量|静态方法 没有差别,否则不能被java所识别;
标注这个注解后能被java识别,它是一个默认参数,java中没有这个,标注后就可以使用了
概述:
代码如图:
概述:
代码如图:
集合类型of 表示为不可变集合,初始化之后就不能进行操作了;而Mutable集合类型表示为可变集合
如果遇到这种问题,可以定义java代码或者中间通过java代码进行处理
apply plugin: "kotlin-kapt"
// 添加生成路径
sourceSets{
main.kotlin.srcDirs+= "build/generated/source/kapt/main"
}
然后更新Gradle,通过Gradle右侧Build命令,使用IDEA的Build不能编译,IDEA还不支持
Kotlin Sript
Java虚拟机应用
前端开发
Android应用开发
Native程序
选择项目类型:
输入项目名称和组名:
然后一直next 成功创建后到主界面;
创建成功后如图所示:
配置noarg插件,它能在程序编译的时候,自动的为对象生成默认的无参构造方法
配置allopen插件,因为kotlin的类都是final的,我们继承它的时候需要open,能在编译的时候去掉final;
以上两个只有编译期能使用
里面配置的如jpa的部分可以根据实际情况决定,不需要可以去掉;
更多可百度学习
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。