美文网首页
Kotlin入门

Kotlin入门

作者: 小楠总 | 来源:发表于2020-01-08 14:25 被阅读0次

Kotlin简介

Kotlin是什么

Kotlin是JetBrains公司开发的一门语言,一圣彼得堡附近的Kotlin岛屿来命名的。Kotlin是运行在JVM上面的一门静态强类型语言,可以编译成JavaScript源码,运行在浏览器上,与Java100%兼容。

Kotlin的特性

为什么有了Java还需要有Kotlin?下面就看看Kotlin的一些特性吧:

  • 空类型安全
  • Lambda表达式
  • 扩展方法
  • 类型推导
  • 胜任Java能做的所有事情,使用起来比Java简单,例如没有句末分号

Kotlin相关参考资料

https://kotlinlang.org

https://blog.jetbrains.com/kotlin/

https://github.com/JetBrains/kotlin

Kotlin环境搭建

Kotlin练习环境搭建之--Hello Word!

下面我们先用IDEA来创建一个项目,打开IDEA,创建项目,选择Kotlin(JVM),如下图所示:

Kotlin创建项目.png
Tips:如果没有Kotlin选项,请先安装Kotlin插件,创建项目需要选择lib库。
Tips:首次创建项目需要Index一两分钟。

与Java一样,在src目录下面创建一个Package,创建.kt文件:

fun main(args: Array<out String>) {
    print("Hello Word\n")
    //创建类的时候不需要new关键字了
    print(MyBean(1, "test bean"))
}

//Kotlin风格的数据对象
data class MyBean(var id: Int, var name: String)

那么程序就会输出:

Hello Word
MyBean(id=1, name=test bean)

Kotlin练习环境搭建之--使用Gradle搭建环境

Gradle是一个依赖管理的工具,以前我们都是直接把jar包等源码直接拷贝进来的,但是这样很麻烦。有了Gradle之后,我们就可以通过脚本或者图形化界面进行依赖管理了,对以后依赖库的升级维护也很方便。

同样用IDEA进行开发,下面我们创建一个项目,选择Gradle、Kotlin,如下图所示:

Gradle创建Java与Kotlin项目.png

接下来配置构件信息,其中包括代表公司或者组织的GroupId,代表自己在公司或者组织里面的代表自己的ArticleFactId,然后就是构件的版本:

配置构件的信息.png

然后就是配置Gradle,这里笔者使用自己本地的Gradle,然后选择生成一些重要的文件夹,例如src/main/java目录:

配置Gradle.png

项目创建好之后如下:

项目一览.png

工具已经帮我们创建好需要的目录了。我们下面来看一些与Gradle相关的重要文件:

settings.gradle:是存放每个module的信息的,其内容如下:

rootProject.name = 'KotlinDemo'

build.gradle,与build相关的脚本,其内容如下:

group 'nan.com'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        //下面的dependencies中,插件的地址
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.4"
    }
}

//标识Java与Kotlin工程,存放着与编译相关的一系列指令集
apply plugin: 'java'
apply plugin: 'kotlin'

//标识Java的版本,这里没有使用到
sourceCompatibility = 1.5

repositories {
    //module中的依赖的地址
    jcenter()
}

//Gradle中最重要的功能--依赖管理
dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.4"
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

使用Gradle进行依赖管理

由于Kotlin中,反射包是独立与基础包的,因此我们以反射这个包为例子,介绍一下使用Gradle进行依赖管理。

修改build.gradle:

//Gradle中最重要的功能--依赖管理
dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.4"
    //增加反射依赖
    compile "org.jetbrains.kotlin:kotlin-reflect:1.0.4"
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

然后就可以在代码中进行反射操作了,例如我们拿到Person类的构造方法:

fun main(args: Array<String>) {
    Person::class.constructors.map {
        print(it)
    }

    //也可以通过代码提示直接改成这种写法
    Person::class.constructors.map(::print)
}

data class Person(var id: Int, var name: String) {

}

Kotlin空指针安全

我们先来看一个例子,我们先创建一个Person类:

data class Person(var id: Int, var name: String) {

}

然后在Java代码中new这个类:

public class Test {
public static void main(String[] args) {
//注意第二个参数传了null
Person p = new Person(1, null);
}
}

运行的时候发现报错:

Exception in thread "main" java.lang.IllegalArgumentException: Parameter specified as non-null is null: method Person.<init>, parameter name
    at Person.<init>(Test.kt)
    at Test.main(Test.java:7)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

因为Kotlin的类中实质上加了@notnull注解。

同样地,我们在Kotlin中使用这个Person,也传个null进去:

fun main(args: Array<String>) {
    val p = Person(1, null)
}

你会发现,根本就编译不过。这就是Kotlin的类型安全的体现了,把一些空指针的问题提前到了编译阶段,而不是运行阶段,这一点真的很重要。

Tips:可以通过code -- Conver Java File to Kotlin File或者直接粘贴,把Java代码转换Kotlin代码。

如果你的Person类中的name可以传null的话,就需要加上"?"标识符,完整的示例如下:

fun main(args: Array<String>) {
    //不会报错了
    val p = Person(1, null)
}

data class Person(var id: Int, var name: String?) {
    
}

Kotlin中的集合

Kotlin中的集合

与Java中用[]代表集合不一样,在Kotlin中用Array<T>表示集合,例如:

fun main(args: Array<String>) {

}

与Java类似,可以在泛型中指定类型应该继承哪个类型,Java中用extends关键字,在Kotlin中用out关键字,例如:

fun main(args: Array<out Bean>) {

}

集合的基本遍历

下面是Kotlin中集合遍历的集中方法:

fun main(args: Array<String>) {

    for (arg in args) {
        print(arg)
    }

    args.map({ print(it) })

    args.map() {
        print(it)
    }

    args.map { print(it) }

    args.map(::print)
}
Tips:命令行参数可以在run--Edit Configuration中修改。
  • 第一种没有什么好说的,与Java类似。

  • 第二种开始,使用了map方法进行遍历,map方法是Kotlin中的Arrays类提供的遍历集合的函数,定义如下:

      //map方法是一个扩展方法,只有一个Lambda表达式参数,接收的是一个T类型的参数,返回R类型。T类型就是我们要迭代的String类型,而R类型没有明确指定
      public inline fun <T, R> Array<out T>.map(transform: (T) -> R): List<R> {
          return mapTo(ArrayList<R>(size), transform)
      }
    

因此呢,map方法可以传进去一个 {表达式} 作为参数。而print接收一个it参数,it是迭代的String,返回的是空类型(Kotlin中空类型是Unit),完全符合map中的Lambda表达式的要求。因此可以传进去。

  • 第三种,既然map只有一个Lambda表达式参数,那么可以把大括号后置,这是第三种。
  • 第四中,在第三种的基础上,既然大括号可以省略,那么前面的()也省略了。
  • 第五种,直接把函数的引用传进去(通过两个分号::)
Kotlin中的空用Unit类型表示,无返回值的函数可以这样写(一般无返回值直接省略而已):
fun main(args: Array<String>) :Unit{

}

使用flatMap扁平化集合

现在有一个需求:

将apple_bus_cat dog_egg_fly good_hook_it
扁平化输出为:apple:5 bus:3 cat:3 dog:3 egg:3 fly:3 good:4 hook:4 it:2 

在Java中是这样做的:

public static void main(String[] args) {
    for (String arg : args) {
        String[] split = arg.split("_");
        for (String s : split) {
            System.out.print(s + ":" + s.length() + " ");
        }
    }
}

在Kotlin中是通过flatMap进行扁平化,然后再通过map进行遍历输出的:

fun main(vararg args: String) {

    args.flatMap {
        it.split("_")
    }.map {
        print("$it:${it.length} ")
    }

}

程序中我们用到了flatMap对集合进行了一次扁平化,返回了一个数组,最终丢给map。下面我们来看看flatMap的源码:

//实际上flatMap也是传入一个Lambda表达式,将T类型(String)的数据转换成可迭代的R类型数据,因此String的split符合要求
public inline fun <T, R> Array<out T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
    return flatMapTo(ArrayList<R>(), transform)
}

//flatMap最终会调用flatMapTo方法,对集合进行扁平化,把每一个转换出来的数据都放到一个列表里面,因此,虽然我们有apple_bus_cat dog_egg_fly good_hook_it三组数据,但是最终被切割成apple bus cat dog egg fly good hook it这样的一个数组,然后再通过map进行遍历输出即可
public inline fun <T, R, C : MutableCollection<in R>> Array<out T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
    for (element in this) {
        val list = transform(element)
        destination.addAll(list)
    }
    return destination
}
Tips:Kotlin中的可变长参数是用vararg关键字来声明的。
Tips:与JS类似,双引号""字符串的拼接中可以使用$符号。
Tips:由于这里迭代中需要传参,因此不可以省略成args.map(::print)这种形式了(这种形式默认是把it传进print方法中了)

相关文章

网友评论

      本文标题:Kotlin入门

      本文链接:https://www.haomeiwen.com/subject/zrishxtx.html