zoukankan      html  css  js  c++  java
  • Kotlin开发springboot项目(二)

    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 = true
    val anotherBoolean: Boolean = false

    val anInt: Int = 8
    val anotherInt: Int = 0xFF
    val moreInt: Int = 0b00000011
    val maxInt: Int = Int.MAX_VALUE
    val minInt: Int = Int.MIN_VALUE

    val aLong: Long = 12368172397127391
    val another: Long = 123
    val maxLong: Long = Long.MAX_VALUE
    val minLong: Long = Long.MIN_VALUE

    val aFloat: Float = 2.0F
    val anotherFloat: Float = 1E3f
    val maxFloat: Float = Float.MAX_VALUE
    val minFloat: Float = -Float.MAX_VALUE

    val aDouble: Double = 3.0
    val anotherDouble: Double = 3.1415926
    val maxDouble: Double= Double.MAX_VALUE
    val minDouble: Double= -Double.MAX_VALUE

    val aShort: Short = 127
    val maxShort: Short = Short.MAX_VALUE
    val minShort: Short = Short.MIN_VALUE

    val aByte:Byte=127
    val maxByte: Byte = Byte.MAX_VALUE
    val 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..-1

    fun 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= 6
    val 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 = """


    $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.kotlin

    import 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 ")
    }
    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:IdeaProjectsHelloworld-kotlinsrcasickotlin>kotlinc hello.kt
    D:IdeaProjectsHelloworld-kotlinsrcasickotlin>kotlin HelloKt
    Hello, 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) -> Int
    val sum = { arg1: Int, arg2: Int ->
    println("$arg1 + $arg2 = ${arg1 + arg2}")
    arg1 + arg2
    }


    // ()-> Unit
    val 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 Score

    class 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) 返回值 Complex
    class 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 Desk

    fun 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 = 1
    private const val USER = 0

    fun 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容器的方式运行工程

  • 相关阅读:
    codeforces#571Div2 D---Vus the Cossack and Numbers【贪心】
    洛谷P1050 循环【java大数】
    洛谷P1972 HH的项链【树状数组】
    uoj#67 新年的毒瘤【Tarjan】
    洛谷1265 公路修建【最小生成树】
    【超实用工具】三维场景绘制工具
    坐标地址批处理工具
    CAD转KML乱码处理
    地理编码逆编码教程
    最新!全球ALOS 12m地形数据介绍及下载
  • 原文地址:https://www.cnblogs.com/gaogaoyanjiu/p/10871885.html
Copyright © 2011-2022 走看看