Kotlin开发springboot项目(二)

╄→尐↘猪︶ㄣ 提交于 2019-12-28 04:21:01

Kotlin开发springboot项目(二)

中文学习网站:

https://www.kotlincn.net/

研究一下kotlin的demo:

https://github.com/JetBrains/kotlin-examples

 

Kotlin 文件以 .kt 为后缀。

包声明

kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。

如果没有指定包,默认为 default 包。

package basic.kotlin.manager.beijing

/**
 * 定义类
 */
class 总经理(var 姓: String) {
    override fun toString(): String {
        return "${姓}经理"
    }
}

 

package basic.kotlin.manager.beijing

import basic.kotlin.manager.beijing.总经理 as 茶水大王   // 起一个别名
/**
 * 包必须声明在非注释的第一行
 */
fun main(args: Array<String>) {
    val manager: 茶水大王 = 茶水大王("张")
    println(manager)
}

 

默认导入

有多个包会默认导入到每个 Kotlin 文件中:
    kotlin.*
    kotlin.annotation.*
    kotlin.collections.*
    kotlin.comparisons.*
    kotlin.io.*
    kotlin.ranges.*
    kotlin.sequences.*
    kotlin.text.*

基本数据类型:

定义常量与变量

可变变量定义:var 关键字

var <标识符> : <类型> = <初始化值>

不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)

val <标识符> : <类型> = <初始化值>
package basic.kotlin/** * 基本数据类型 *  变量名称:变量类型=变量值 */val aBoolean: Boolean = trueval anotherBoolean: Boolean = falseval anInt: Int = 8val anotherInt: Int = 0xFFval moreInt: Int = 0b00000011val maxInt: Int = Int.MAX_VALUEval minInt: Int = Int.MIN_VALUEval aLong: Long = 12368172397127391val another: Long = 123val maxLong: Long = Long.MAX_VALUEval minLong: Long = Long.MIN_VALUEval aFloat: Float = 2.0Fval anotherFloat: Float = 1E3fval maxFloat: Float = Float.MAX_VALUEval minFloat: Float = -Float.MAX_VALUEval aDouble: Double = 3.0val anotherDouble: Double = 3.1415926val maxDouble: Double= Double.MAX_VALUEval minDouble: Double= -Double.MAX_VALUEval aShort: Short = 127val maxShort: Short = Short.MAX_VALUEval minShort: Short = Short.MIN_VALUEval aByte:Byte=127val maxByte: Byte = Byte.MAX_VALUEval minByte: Byte = Byte.MIN_VALUE
val aChar: Char = '0'val bChar: Char = '中'val cChar: Char = '\u56fd'val dChar: Char = '\u000f'
fun main(args: Array<String>) {    println(anotherInt)    println(moreInt)    println(maxInt)    println(Math.pow(2.0, 31.0) - 1)    println(minInt)    println( - Math.pow(2.0, 31.0))    println(maxLong)    println(Math.pow(2.0, 63.0) - 1)    println(minLong)    println(- Math.pow(2.0, 63.0))    println(aFloat)    println(anotherFloat)    println(maxFloat)    println(minFloat)    println(maxDouble)    println(minDouble)    println(maxShort)    println(minShort)    println(aByte)    println(maxByte)    println(minByte)    println(aChar)    println(bChar)    
   println("Unicode:"+cChar) // 需要转义才能打印   println("Unicode:"+dChar) // 需要转义才能打印
}

 Range区间

package basic.kotlin/** * Range 区间 */val range: IntRange = 0..1024 // [0, 1024]  闭区间val range_exclusive: IntRange = 0 until 1024 // [0, 1024) = [0, 1023] 开区间val emptyRange: IntRange = 0..-1fun main(args: Array<String>) {    println(emptyRange.isEmpty())  // 是否为空    println(range.contains(50))    // 是否包含    println(50 in range)           // 是否在这个区间    for(i in range_exclusive){     // 循环遍历        print("$i, ")    }}

 

 kotlin不支持隐式转换

package basic.kotlin/** * 隐式转换 与 字符串类型 */val aInt:Int= 6val bLong:Long= aInt.toLong() // int整形转换为long类型需要显示转换,在kotlin中不支持隐式转换val string: String = "HelloWorld"val fromChars: String = String(charArrayOf('H','e','l','l','o','W','o','r','l','d'))fun main(args: Array<String>) {    println(bLong)    println(string == fromChars)  // 双等号 比较内容 相当于java中的equals    println(string === fromChars) // 三等号 比较引用 相当于java 中比较的引用的地址    println("接下来我们要输出:" + string)    val arg1: Int = 0    val arg2: Int = 1    println("" + arg1 + " + " + arg2 + " = " + (arg1 + arg2)) // java传统方式进行字符串拼接    println("$arg1 + $arg2 = ${arg1 + arg2}") // 字符串模板进行字符拼接    //Hello "Trump"    val sayHello : String = "Hello \"Trump\""   // 双引号转义    println(sayHello)    //salary    val salary: Int = 1000    //$salary    println("$$salary")    println("\$salary")    // 三个双引号的字符串原样输出,在这种字符串模板拼接时,\ 进行转义时不起作用    val rawString: String = """        \t        \n        $salary        \$salary      $ salary    """    println(rawString)    println(rawString.length)}

kotlin中Any是所有类的父类

package com.basic.kotlin/** * 对象继承关系 */// 类的定义方式一:class 妹子(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音)// 类的定义方式二:class 帅哥(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音){    fun say(){        println("我最帅")    }}class 大叔(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音){    init{        println("我有房、有车、有存款,我在父类的init方法后运行,在自己的实例每次创建被new时先运行")    }}open class person(var 性格: String, var 长相: String, var 声音: String){    init {        println("new 了一个${this.javaClass.simpleName}, ta性格:$性格, 长相:$长相, 声音:$声音")    }}fun main(args: Array<String>) {    val girl: 妹子 = 妹子("温柔", "甜美", "动人")    println(girl is person)    val boy: 帅哥 = 帅哥("彪悍", "帅气", "浑厚")    boy.say()    val uncle: 大叔 = 大叔("稳重", "成熟", "洪亮")}

 空类型安全

 

package basic.kotlin/** * 空值安全 * 安全的kotlin写法 */fun getName(): String?{ // ? 表示返回值的String类型允许为null    return null}fun main(args: Array<String>) {    val str: String? = null  //值允许为空    println(str?.length)     //值为空直接返回null    val value: String? = "HelloWorld"    println(value!!.length)  // 已经明确知道不为空,!! 告诉编译器,我知道是不为空了,你编译吧    val name: String = getName() ?: return   // ? 表示允许为null 为空直接返回,下边的打印语句不会执行了    println(name.length)}

智能类型转换

 定义一个父类

/**
 * 父类
 */
public class Parent {
}

定义一个子类

/**
 * 子类继承父类
 */
public class Child extends Parent {
    public String getName(){
        return "Child";
    }
}

 类型转换

package basic.kotlin/** * 智能识别类型转换 * 安全的kotlin写法 */fun main(args: Array<String>) {    val p: Parent = Parent()    val c: Parent = Child()    if (c is Child)   // 类型相等,就可以执行方法体的内容        println(c.name)    val child: Child? = p as? Child   // 转换失败不让其抛出异常,返回个null ,不带?就会和java原生语法一样抛出异常    println(child)    val string: String? = "Hello"    if(string != null)        println(string.length)  // 智能甄别 ,前边判断了,后边不用判断了}

 数组

package basic.kotlinimport basic.kotlin.manager.beijing.总经理 as m1/** * 数组 */val arrayOfInt: IntArray = intArrayOf(1,3,5,7)val arrayOfChar: CharArray = charArrayOf('H', 'e','l','l','o','W','o','r','l','d')val arrayOfString: Array<String> = arrayOf("我", "是", "码农")val arrayOf经理: Array<m1> = arrayOf(m1("张"),m1("李"))fun main(args: Array<String>) {    println(arrayOfInt.size)    for(int in arrayOfInt){        print("$int \t")    }    println()    println(arrayOfString.joinToString(""))    println(arrayOf经理[1])    arrayOf经理[1] = m1("王")    println(arrayOf经理[1]) // 取出第二个元素    println(arrayOfChar.joinToString()) // 字符串连接 默认逗号    println(arrayOfChar.joinToString("")) // 空字符串连接 ,就是一个完整的字符串    println(arrayOfInt.slice(1..2))  // 字符串区间截取子串    println(arrayOfInt.slice(0..1))  // 字符串区间截取子串}

idea 查看字节码 bytecode插件 (jclasslib Bytecode Viewer、ASM Bytecode Viewer )

jclasslib Bytecode Viewer


然后重启idea===>重新编译(构建项目)


然后能够直接看java文件的字节码



ASM Bytecode Viewer


安装完了之后同样需要重新编译,然后可以直接查看java文件的asm 字节码



 

 在使用 intellij idea 编写 kotlin 的时候,我们可以查看当前 kotlin 文件的字节码。
Tools → Kotlin → Show Kotlin Bytecode

当然字节码是很难看懂的。没关系,我们可以把字节码再反编译成 java 代码。

 

 

 

Windows下安装和配置Kotlin

参考文档:https://www.kotlincn.net/docs/tutorials/command-line.html

在JDK安装完成后,就可以安装Kotlin了。Kotlin是跨平台的,目前支持3种IDE:IntelliJ IDEA、Android Studio和Eclipse。不过在这一节,我们先不考虑IDE的事情。

与Java一样,安装Kotlin后,首先看看是否可以通过命令行方式运行Kotlin程序,这是入门Kotlin要进行的第一步。本节只考虑如何在Windows下安装和配置Kotlin环境,首先进入下面列出的Kotlin官网。

https://kotlinlang.org

将页面滚动到下半部分,会看到如图所示的4个下载区域。最右侧的Compiler是Kotlin编译器的下载页面。

将压缩包解压放在自己喜欢的位置,然后仿照“配置JDK环境变量”的方式配置Kotlin的环境变量。

如果在命令行下输入kotlinc显示类似如下界面,说明配置成功。

 编写一个hello.kt,如下

fun main(args: Array<String>) {
    println("Hello, World!")
}

使用kotlinc hello.kt编译上面的文件,这时会在同一目录下生成一个HelloKt.class,尝试用java命令来运行HelloKt,结果会是NoClassDefFoundError!

那么,应该如何运行这段代码呢?根据官网的介绍大概是以下两种方式。

方式一:使用Kotlin运行这段代码

D:\IdeaProjects\Helloworld-kotlin\src\basic\kotlin>kotlinc hello.ktD:\IdeaProjects\Helloworld-kotlin\src\basic\kotlin>kotlin HelloKtHello, World!

 

方式二:使用本地JVM运行这个JAR包

官方的命令为:kotlinc hello.kt -include-runtime -d hello.jar 

应该很好理解,运行上述命令之后将得到一个hello.jar,运行这个JAR包:java -jar -hello.jar 

D:\labs>java -jar hello.jar
Hello, World!

证明Kotlin是完全兼容JVM的

 

 


package basic.kotlin.test/** * var 与  val 定义变量: *      1、var内容可变,可以重新赋值 *      2、val内容不可变,不可以重新赋值 *      3、类型推导 * val修饰的变量相当于java中被final修饰的类型变量--------运行时常量 * 当被const修饰时,编译器会在编译期间编译为具体的值,否则就是还是对象的引用 ----------编译期常量 * **/const val FINAL_HELLO_WORLD: String = "HelloWorld"  // 不可以重新赋值var helloWorld: String = FINAL_HELLO_WORLD          // 可以重新赋值val FINAL_HELLO_CHINA = "HelloChina"                // 类型推导,由编译器判断。// 默认返回值 Unit 相当于java中的void,就是什么都不返回,也可省略fun main(args: Array<String>) { // (Array<String>) -> Unit//    FINAL_HELLO_WORLD="qqqq"    helloWorld="123456"   // 对var 修饰的常量进行重新赋值    println(helloWorld)    println(FINAL_HELLO_CHINA)    println("hello ${args[0]}")    var arrayOfstr: Array<String> = arrayOf("1","3")    checkArgs(arrayOfstr)    val arg1 = arrayOfstr[0].toInt()    val arg2 = arrayOfstr[1].toInt()    println("$arg1 + $arg2 = ${sum(arg1, arg2)}")    println(int2Long(3))    println(sum(1,3))    println(sum.invoke(1,3))  // invoke是 运算符重载    arrayOfstr.forEach(::println)  // reference 写法// 不加ForEach@ 是退出forEach所在的函数,后面的代码不会被执行// 加ForEach@ 是退出整个for循环,后面的代码依然会被执行    arrayOfstr.forEach ForEach@{        if(it == "3") return@ForEach        println(it)    }    println("The End")    println(sum)    println(int2Long)    println(::printUsage is ()-> Unit)}fun checkArgs(args: Array<String>) {    if (args.size != 2) {        printUsage()        System.exit(-1)    }}// 函数定义 --- 无返回值fun printUsage() {    println("请传入两个整型参数,例如 1 2") // (Any?) -> Unit} // ()->Unit// lambda 表达式  (Int, Int) -> Intval sum = { arg1: Int, arg2: Int ->    println("$arg1 + $arg2 = ${arg1 + arg2}")    arg1 + arg2}// ()-> Unitval printlnHello = {    println("Hello")}// 匿名函数定义  有返回值val int2Long = fun(x: Int): Long {    return x.toLong()}}

 

 

 

 

 IDEA按键失效:常用快捷键:Ctrl+C  Ctrl+V  选中删除都不起效,原因是IDEA勾选了Vim模式,

Tools,Vim Emulator,前面会有一个√,可,如图:

把那个√取消即可解决问题。

kotlin属性和函数

package basic.kotlin.function/** * 测试 属性和方法  属性的getter 和setter是默认实现,也可以手动重写 * * 默认访问修饰符 public * 私有的:protected、private * * lateinit 是属性延迟初始化修饰符 */class Scoreclass Stu{    var age = 0  // getter 和 setter 只能放在当前属性的正下方    get() {        println("测试getter方法")        return field    }    set(value) {        println("测试setter方法")        field=value    }    lateinit var name: String  // 字符串引用类型懒加载赋值  在使用是必须初始化    lateinit var score: Score      // 自定义对象类型懒加载赋值  在使用是必须初始化    val e: Score by lazy {         // val 修饰的懒加载赋值,通过 by lazy ,在使用是必须初始化        println("初始化 Score")        Score()    }    var cc: String? = null}fun main(args: Array<String>) {    val stu = Stu()    println(stu.age)  // 等价于 stu.getAge()    stu.age=30    println(stu.age)  // 使用之前需要初始化    stu.name="张三"    // 使用之前需要初始化    println(stu.name)  // lateinit property name has not been initialized    println(stu.e)    // 在定义时初始化    stu.score = Score()     // 初始化赋值    println(stu.score)      // 打印的对象名,使用之前初始化    println(stu.cc?.length) // 空值的条件判断}

 kotlin的运算符

package basic.kotlin.function/** * 运算符:本质上就是一个函数 * + 实际上对应的是kotlin的默认plus 方法 * 我们可以自己定义plus的重载方法 写自己的运算符实现 * *///c1.plus(c2) 返回值 Complexclass Complex(var real: Double, var imaginary: Double){   //  重载方法:1   参数Complex, 返回值 Complex    operator fun plus(other: Complex): Complex{        return Complex(real + other.real, imaginary + other.imaginary)    }    //  重载方法:2  参数Complex,返回值 Complex    operator fun plus(other: Int): Complex{        return Complex(real + other, imaginary)    }    //  重载方法:3 参数Any,返回值 Int    operator fun plus(other: Any): Int {        return (real + imaginary).toInt()    }    //  重载方法:4    operator fun invoke(): Double{        return Math.hypot(real, imaginary) // q取模运算    }    override fun toString(): String {        return "结果:$real + ${imaginary}"    }}//中缀符号表达式,用于两个对象间的运算class Book{     infix fun on(any: Any): Boolean{        return false    }}class Deskfun main(args: Array<String>) {//   + 实际上对应的是kotlin的默认plus 方法    println(1 + 2)    val c1 = Complex(3.0, 4.0)    val c2 = Complex(2.0, 5.0)    println(c1 + c2)      // 结果:5.0 + 9.0 第一个重载方法 等价于  println(c1.plus(c2))    println(c1 + 5)       // 结果:8.0 + 4.0第二个重载方法 等价于 println(c1.plus(5))    println(c1 + "haha")  // 7 第三个重载方法 等价于 println(c1.plus("haha"))    println(c1())         // 5.0 第四个重载方法 等价于 println(c1.invoke())    //字符串包含    val arrayOfStr: Array<String> = arrayOf("my","name","is黑客")    if("name" in arrayOfStr){  // 等价于  arrayOfStr.contains("name")        println(arrayOfStr[arrayOfStr.indexOf("name") + 1])    }    if(Book() on Desk()){ // dsl    }}

分支表达式 if、when

 

package basic.kotlin.function/** * 分支表达式 if 、when */private const val USERNAME = "kotlin"private const val PASSWORD = "123"private const val ADMIN_USER = "admin"private const val ADMIN_PASSWD = "admin"private const val DEBUG = 1private const val USER = 0fun main(args: Array<String>) {    val x = 5    when(x){ // 只会执行其中的一个        is Int -> println("Hello $x")  // 判断 是否是int类型        in 1..100 -> println("$x is in 1..100") // 判断是否是在区间中        !in 1..100 -> println("$x is not in 1..100") // 判断是否是不在区间中        args[0].toInt() -> println("x == args[0]") // x 和当前表达式是否一样    }    // 相当于if else    val wh = when{        args.isNotEmpty() && args[0] == "1"        -> 1        else -> 0    }    println(wh)    // if表达式 带返回值    val mode = if(args.isNotEmpty() && args[0] == "1"){        DEBUG    }else{        USER    }    println("请输入用户名:")    val username = readLine()    println("请输入密码:")    val passwd = readLine()    if(mode == DEBUG && username == ADMIN_USER && passwd == ADMIN_PASSWD) {        println("管理员登录成功")    }else if(username == USERNAME && passwd == PASSWORD){        println("登录成功")    }else{        println("登录失败")    }}

 

 

package basic.kotlin.function/** * 跳过continue 和 跳出break 循环 */class Student{    fun isNotClothedProperly(): Boolean{        return false    }}fun main(args: Array<String>) {    val students = ArrayList<Student>()    val you = Student()    for (student in students){        if(student == you) continue        if(student.isNotClothedProperly()){            break        }    }}

 

package basic.kotlin.function/** * for 循环 和 while 循环 语句 */fun main(args: Array<String>) {    val arrayOfStr: Array<String> = arrayOf("my","name","is黑客")    var x = 5    while(x > 0){        println(x)        x--    }    do{        println(x)        x--    }while (x > 0)    for (arg in arrayOfStr){        println(arg)    }    for((index, value) in arrayOfStr.withIndex()){        println("$index -> $value")    }    for(indexedValue in arrayOfStr.withIndex()){        println("${indexedValue.index} -> ${indexedValue.value}")    }    val list = MyIntList()    list.add(1)    list.add(2)    list.add(3)    for(i in list){        println(i)    }}class MyIterator(val iterator: Iterator<Int>){    operator fun next(): Int{        return iterator.next()    }    operator fun hasNext(): Boolean{        return iterator.hasNext()    }}class MyIntList{    private val list = ArrayList<Int>()    fun add(int : Int){        list.add(int)    }    fun remove(int: Int){        list.remove(int)    }    operator fun iterator(): MyIterator{        return MyIterator(list.iterator())    }}

 异常捕获

 

package basic.kotlin.function/** * 异常捕获 */fun main(args: Array<String>) {    val res = try {        val result = 1/0    }catch (e: Exception){        println("程序出现了未知异常,可能是您的人品太差了。${e.message}")        0    }finally {        println("谢谢您使用我们的加法计算器")    }    println(res)} 

 具名参数:参数赋值到具体名称,没有顺序

变长参数:在java里是最后一个参数,在kotlin没有这种限制

默认参数:调用时不传入参数,可以采用设置默认值

package basic.kotlin.function/** *  具名参数:参数赋值到具体名称,没有顺序 *  变长参数:在java里是最后一个参数,在kotlin没有这种限制 *  默认参数:调用时不传入参数,可以采用设置默认值 */fun main(vararg args: String) {//    for (arg in args){//        println(arg)//    }    val list = arrayListOf(1,3,4,5)    val array = intArrayOf(1,3,4,5)    hello(3.0, *array)}fun hello(double: Double, vararg ints: Int, string: String = "Hello"){    println(double)    ints.forEach(::println)    println(string)}

 

先以 Http Servlet 创建 Web 应用 为例

在导入工程后,通过gradle的工具创建生成war,war包的名称和settings.gradle的 rootProject.name = 'servlet-web-applications' 一致

方式一:打成war包运行

 手动放到tomcat容器,双击运行tomcat。

 

方式二:

IDEA 中添加tomcat容器的方式运行工程

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!