遇见 Kotlin

Bennyhuo

个人介绍

霍丙乾 Bennyhuo

  • 腾讯地图 Android 工程师
  • Kotlin “布道师”
  • Kotlin 微信公众号
  • 目前国内第一套 Kotlin 视频教程

Kotlin 是什么

Kotlin 官网

静态语言

  • 与 Java 完美兼容
  • 有完美的 IDE 提示
  • 确定的类型给人以安全感
import kotlin.browser.document

/**
 * Created by benny on 4/30/17.
 */

fun main(args: Array<String>) {
    document.writeln("Hello World from Kotlin-js")
}

Observable
    .from("HelloWorld".toCharArray().asIterable())
    .zipWith(
            Observable.interval(1, 1, TimeUnit.SECONDS), 
            { a, b -> "$a, $b" })
    .subscribe(::println)

Java 虚拟机


Observable
    .from("HelloWorld".toCharArray().asIterable())
    .zipWith(
            Observable.interval(1, 1, TimeUnit.SECONDS), 
            { a, b -> "$a, $b" })
    .subscribe(::println)
// ================net/println/kt07/LambdaKt.class =================
// class version 50.0 (50)
// access flags 0x31
public final class net/println/kt07/LambdaKt {


  // access flags 0x19
  public final static main([Ljava/lang/String;)V
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 0
    LDC "args"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 16 L1
   L2
    LINENUMBER 20 L2
   L3
    LINENUMBER 16 L3
   L4
    LINENUMBER 17 L4
   L5
    LINENUMBER 16 L5
    LDC "HelloWorld"
    ASTORE 1
   L6
    ALOAD 1
   L7
    INVOKEVIRTUAL java/lang/String.toCharArray ()[C
    DUP
    LDC "(this as java.lang.String).toCharArray()"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L8
   L9
    LINENUMBER 16 L9
    INVOKESTATIC kotlin/collections/ArraysKt.asIterable ([C)Ljava/lang/Iterable;
    INVOKESTATIC rx/Observable.from (Ljava/lang/Iterable;)Lrx/Observable;
    LCONST_1
    LCONST_1
    GETSTATIC java/util/concurrent/TimeUnit.SECONDS : Ljava/util/concurrent/TimeUnit;
    INVOKESTATIC rx/Observable.interval (JJLjava/util/concurrent/TimeUnit;)Lrx/Observable;
    GETSTATIC net/println/kt07/LambdaKt$main$1.INSTANCE : Lnet/println/kt07/LambdaKt$main$1;
    CHECKCAST rx/functions/Func2
   L10
    LINENUMBER 17 L10
    INVOKEVIRTUAL rx/Observable.zipWith (Lrx/Observable;Lrx/functions/Func2;)Lrx/Observable;
    NEW net/println/kt07/LambdaKt$sam$Action1$75bbf535
    DUP
    GETSTATIC net/println/kt07/LambdaKt$main$2.INSTANCE : Lnet/println/kt07/LambdaKt$main$2;
    CHECKCAST kotlin/jvm/functions/Function1
    DUP
    IFNONNULL L11
    POP
    POP2
    ACONST_NULL
    GOTO L12
   L11
    INVOKESPECIAL net/println/kt07/LambdaKt$sam$Action1$75bbf535.<init> (Lkotlin/jvm/functions/Function1;)V
   L12
    CHECKCAST rx/functions/Action1
   L13
    LINENUMBER 20 L13
    INVOKEVIRTUAL rx/Observable.subscribe (Lrx/functions/Action1;)Lrx/Subscription;
    POP
   L14
    LINENUMBER 22 L14
    LDC 15000
    INVOKESTATIC java/lang/Thread.sleep (J)V
   L15
    LINENUMBER 23 L15
    RETURN
   L16
    LOCALVARIABLE args [Ljava/lang/String; L0 L16 0
    MAXSTACK = 6
    MAXLOCALS = 2

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=2, d1={"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\u0008\u0002\u001a\u0019\u0010\u0000\u001a\u00020\u00012\u000c\u0010\u0002\u001a\u0008\u0012\u0004\u0012\u00020\u00040\u0003\u00a2\u0006\u0002\u0010\u0005\u00a8\u0006\u0006"}, d2={"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module kt07_main"})
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$1 null null
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$2 null null
  // compiled from: Lambda.kt
  // debug info: SMAP
Lambda.kt
Kotlin
*S Kotlin
*F
+ 1 Lambda.kt
net/println/kt07/LambdaKt
*L
1#1,28:1
*E

}


// ================net/println/kt07/LambdaKt$main$1.class =================
// class version 50.0 (50)
// access flags 0x30
// signature <T1:Ljava/lang/Object;T2:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;Lrx/functions/Func2<TT;TT2;TR;>;
// declaration: net/println/kt07/LambdaKt$main$1<T1, T2, R> implements rx.functions.Func2<T, T2, R>
final class net/println/kt07/LambdaKt$main$1 implements rx/functions/Func2  {


  // access flags 0x1041
  public synthetic bridge call(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    ALOAD 0
    ALOAD 1
    CHECKCAST java/lang/Character
    ALOAD 2
    CHECKCAST java/lang/Long
    INVOKEVIRTUAL net/println/kt07/LambdaKt$main$1.call (Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;
    ARETURN
    MAXSTACK = 3
    MAXLOCALS = 3

  // access flags 0x11
  public final call(Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;
  @Lorg/jetbrains/annotations/NotNull;() // invisible
   L0
    LINENUMBER 19 L0
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    LDC ", "
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
   L1
    ARETURN
   L2
    LOCALVARIABLE this Lnet/println/kt07/LambdaKt$main$1; L0 L2 0
    LOCALVARIABLE a Ljava/lang/Character; L0 L2 1
    LOCALVARIABLE b Ljava/lang/Long; L0 L2 2
    MAXSTACK = 2
    MAXLOCALS = 3

  // access flags 0x0
  <init>()V
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x19
  public final static Lnet/println/kt07/LambdaKt$main$1; INSTANCE

  // access flags 0x8
  static <clinit>()V
    NEW net/println/kt07/LambdaKt$main$1
    DUP
    INVOKESPECIAL net/println/kt07/LambdaKt$main$1.<init> ()V
    PUTSTATIC net/println/kt07/LambdaKt$main$1.INSTANCE : Lnet/println/kt07/LambdaKt$main$1;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3, d1={"\u0000\u0018\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u000c\n\u0002\u0008\u0002\n\u0002\u0010\u0009\n\u0002\u0008\u0002\u0010\u0000\u001a\u00020\u00012\u000e\u0010\u0002\u001a\n \u0004*\u0004\u0018\u00010\u00030\u00032\u000e\u0010\u0005\u001a\n \u0004*\u0004\u0018\u00010\u00060\u0006H\n\u00a2\u0006\u0004\u0008\u0007\u0010\u0008"}, d2={"<anonymous>", "", "a", "", "kotlin.jvm.PlatformType", "b", "", "call", "(Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;"})
  OUTERCLASS net/println/kt07/LambdaKt main ([Ljava/lang/String;)V
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$1 null null
  // compiled from: Lambda.kt
}


// ================net/println/kt07/LambdaKt$sam$Action1$75bbf535.class =================
// class version 50.0 (50)
// access flags 0x30
final class net/println/kt07/LambdaKt$sam$Action1$75bbf535 implements rx/functions/Action1  {


  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3)

  // access flags 0x1012
  private final synthetic Lkotlin/jvm/functions/Function1; function

  // access flags 0x0
  <init>(Lkotlin/jvm/functions/Function1;)V
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    ALOAD 0
    ALOAD 1
    PUTFIELD net/println/kt07/LambdaKt$sam$Action1$75bbf535.function : Lkotlin/jvm/functions/Function1;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1011
  // signature (TT;)V
  // declaration: void call(T)
  public final synthetic call(Ljava/lang/Object;)V
   L0
    ALOAD 0
    GETFIELD net/println/kt07/LambdaKt$sam$Action1$75bbf535.function : Lkotlin/jvm/functions/Function1;
    ALOAD 1
    INVOKEINTERFACE kotlin/jvm/functions/Function1.invoke (Ljava/lang/Object;)Ljava/lang/Object;
    DUP
    LDC "invoke(...)"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    POP
    RETURN
   L1
    LOCALVARIABLE this Lrx/functions/Action1; L0 L1 0
    LOCALVARIABLE t Ljava/lang/Object; L0 L1 1
    MAXSTACK = 3
    MAXLOCALS = 2
  // compiled from: Lambda.kt
}


// ================net/println/kt07/LambdaKt$main$2.class =================
// class version 50.0 (50)
// access flags 0x30
// signature Lkotlin/jvm/internal/FunctionReference;Lkotlin/jvm/functions/Function1<Ljava/lang/Object;Lkotlin/Unit;>;
// declaration: net/println/kt07/LambdaKt$main$2 extends kotlin.jvm.internal.FunctionReference implements kotlin.jvm.functions.Function1<java.lang.Object, kotlin.Unit>
final class net/println/kt07/LambdaKt$main$2 extends kotlin/jvm/internal/FunctionReference  implements kotlin/jvm/functions/Function1  {


  // access flags 0x1041
  public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
    ALOAD 0
    ALOAD 1
    INVOKEVIRTUAL net/println/kt07/LambdaKt$main$2.invoke (Ljava/lang/Object;)V
    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x11
  public final invoke(Ljava/lang/Object;)V
    @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0
   L0
    LINENUMBER 20 L0
   L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L2
   L3
    RETURN
   L4
    LOCALVARIABLE this Lnet/println/kt07/LambdaKt$main$2; L0 L4 0
    LOCALVARIABLE p1 Ljava/lang/Object; L0 L4 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x11
  public final getOwner()Lkotlin/reflect/KDeclarationContainer;
    LDC Lkotlin/io/ConsoleKt;.class
    LDC "production sources for module kt07_main"
    INVOKESTATIC kotlin/jvm/internal/Reflection.getOrCreateKotlinPackage (Ljava/lang/Class;Ljava/lang/String;)Lkotlin/reflect/KDeclarationContainer;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x11
  public final getName()Ljava/lang/String;
    LDC "println"
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x11
  public final getSignature()Ljava/lang/String;
    LDC "println(Ljava/lang/Object;)V"
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x0
  <init>()V
    ALOAD 0
    ICONST_1
    INVOKESPECIAL kotlin/jvm/internal/FunctionReference.<init> (I)V
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x19
  public final static Lnet/println/kt07/LambdaKt$main$2; INSTANCE

  // access flags 0x8
  static <clinit>()V
    NEW net/println/kt07/LambdaKt$main$2
    DUP
    INVOKESPECIAL net/println/kt07/LambdaKt$main$2.<init> ()V
    PUTSTATIC net/println/kt07/LambdaKt$main$2.INSTANCE : Lnet/println/kt07/LambdaKt$main$2;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3, d1={"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0000\n\u0002\u0018\u0002\n\u0002\u0008\u0003\u0010\u0000\u001a\u00020\u00012\u0017\u0010\u0002\u001a\u0013\u0018\u00010\u0003\u00a2\u0006\u000c\u0008\u0004\u0012\u0008\u0008\u0005\u0012\u0004\u0008\u0008(\u0006\u00a2\u0006\u0002\u0008\u0007"}, d2={"<anonymous>", "", "p1", "", "Lkotlin/ParameterName;", "name", "message", "invoke"})
  OUTERCLASS net/println/kt07/LambdaKt main ([Ljava/lang/String;)V
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$2 null null
  // compiled from: Lambda.kt
  // debug info: SMAP
Lambda.kt
Kotlin
*S Kotlin
*F
+ 1 Lambda.kt
net/println/kt07/LambdaKt$main$2
*L
1#1,28:1
*E

}


// ================META-INF/production sources for module kt07_main.kotlin_module =================


net.println.kt07LambdaKt

Kotlin-Android

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        verticalLayout{
            imageView {
                async {
                    imageBitmap = await{ loadImage(url) }
                }
            }
        }
    }
}

Kotlin-Js

import kotlin.browser.document

fun main(args: Array<String>) {
    document.writeln("Hello World from Kotlin-js")
}
if (typeof kotlin === 'undefined') {
  throw new Error("Error loading module 'kotlin-javascript'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'kotlin-javascript'.");
}
this['kotlin-javascript'] = function (_, Kotlin) {
  'use strict';
  function main(args) {
    document.writeln('Hello World from ' + browerInfoString());
  }
  _.main_kand9s$ = main;
  Kotlin.defineModule('kotlin-javascript', _);
  main([]);
  return _;
}(typeof this['kotlin-javascript'] === 'undefined' ? {} : this['kotlin-javascript'], kotlin);

Kotlin-Native 

#ifndef CN_KOTLINER_H
#define CN_KOTLINER_H

void printHello();

int factorial(int n);

#endif
import cn.kotliner.native.*

fun main(args: Array<String>){
    printHello()
    (1 .. 5).map(::factorial).forEach(::println)
}

Kotlin 给我们带来什么

简洁性

data class Customer(
    val name: String, 
    val email: String, 
    val company: String)

数据类

val positiveNumbers = list.filter { it > 0 }

Lambda表达式

单例

object ThisIsASingleton {
    val companyName: String = "JetBrains"
}

异步

async {
    val bitmap = await{ loadImage(url) }
}

安全性

override 关键字

空类型安全

var output: String
output = null   // Compilation error
override fun doTask(){
    ...
}

主构造器

class PhoneCall(val id: String){

    constructor(val id: String, val caller: String): this(id){
        ...
    }
}

通用性

兼容性

都有谁在用 Kotlin

Google

Android 官方开发语言

Android 官方开发语言

Android 官方开发语言

Square

Jake Wharton 的公司

大神已经贡献了不少 Kotlin 框架

沪江

绝大部分代码已经替换为 Kotlin,是国内较早采用 Kotlin 的公司

花瓣网

Android app 100% 使用 Kotlin 开发

快乐迭代

不要 Java,只用 Kotlin 的公司

Coursera

Android app 部分代码使用 Kotlin 开发

Uber

主要用来开发内部工具,例如Gradle 插件、注解处理器等等

你该不该学 Kotlin

没有 Java 基础,我应该学吗?

  • 当然应该学,而且还要学更多其他语言
  • Kotlin 与 Java 关系密切,最好把 Java 基础打好

不学 Java 可以直接开发 Android 吗?

  • 可以用来开发 Android 的语言很多
  • 主流是 Java,还是要打好 Java 基础

你该不该用 Kotlin

用 Kotlin 开发 Android 靠谱吗?

  • Google 说,靠谱啊
  • Jake Wharton 大神早就说,性能没问题,放心大胆地用
  • 国内有不少公司尝试,还没听说不好的
  • 问题:需要与你的协作者沟通好

Kotlin 会不会慢慢把 Java 取代了?

  • 短期内不会,而且我们也没必要担心这个
  • 不会写 Kotlin 的人倒是可能被 Java&Kotlin 给淘汰掉

Kotlin 学习资料

公众号 Kotlin

  • 周一发文
  • 技术干货
  • 社区动态

Kotlin 中文网

Kotlin 中文博客

Kotlin 中文问答社区

KotlinThree

视频教程

谢谢!

Copy of 遇见 Kotlin

By 霍丙乾

Copy of 遇见 Kotlin

Kotlin 是一门静态语言,兼容 Java,运行在 JVM、Android、以及浏览器上。

  • 1,759