文章寫於 2017 年,首發於微信公衆號:字節流動
Google I/O 2017 宣佈在 Android Studio 3.0 將默認支持 Kotlin 用於 Android 開發. 請注意 Google 只是宣佈 Kotlin 作爲 Android 開發的一級語言,並沒有說要用其取代 Java ,這裏很多無腦媒體進行了過度解讀。作爲一名合格的程序員,首先要理性看待技術迭代更新,同時要對新事物保持強烈的好奇心。
Kotlin 簡介
Kotlin 來自於捷克一家牛逼軟件研發公司 JetBrains ,很多優秀的 IDE,如 IntelliJ IDEA、PyCharm、WebStorm 等都是它的傑作,包括 Google 官方的 Android IDE – Android Studio ,也是 IntelliJ IDEA 的插件版。
Kotlin 源於 JetBrains 的聖彼得堡團隊,名稱取自聖彼得堡附近的一個小島 ( Kotlin Island ) ,JetBrains 在 2010 年首次推出 Kotlin 編程語言,並在次年將之開源。
Kotlin 的特點
Kotlin 是一個基於 JVM 的編程語言,與 Java 有很深的淵源。它能與 Java 100% 互通,具備諸多 Java 尚不支持的新特性。Kotlin 可以編譯成 Java 字節碼,也可以編譯成 JavaScript ,方便在沒有 JVM 的設備上運行,可用於移動端以及 Web 開發,是一種全棧式開發語言。
Java to Kotlin
下面是 Java to Kotlin 主要語法,以便於你快速認識 Kotlin 這門語言。
變量
Java
String lan = "Hello Kotlin";
final String lan = "Hello Kotlin";
Kotlin
var lan = "Hello Kotlin"
val lan = "Hello Kotlin"
打印字符串
Java
System.out.print("Hello Kotlin");
System.out.println("Hello Kotlin");
Kotlin
print("Hello Kotlin");
println("Hello Kotlin");
字符串模板
Java
String name = "haohao";
int age = 25;
String msg = "I am " + name + ", " + age + " years old.";
String text = "Hello Kotlin\n" +
"Hello Android\n" +
"Hello TensorFlow";
Kotlin
var name = "haohao";
var age = 25;
var msg = "I am $name , $age years old.";
var text = """
|Hello Kotlin
|Hello Android
|Hello TensorFlow
""".trimMargin()
// trimMargin() 去除連接符 `|`
空聲明
Java
String name = null;
Kotlin
var name: String? = null // `?` 聲明變量可爲 null
判空
Java
if (name != null) {
int len = name.length;
}
Kotlin
name?.let{
val len = name.length
}
邏輯表達式
Java
String y = x > 6 ? "x > 6" : "x <= 6";
Kotlin
var y = if (x > 6)
"x > 6"
else "x <= 6"
類型判斷及轉換
Java
if (obj instanceof Person) {
Person p = (Person) obj;
}
Kotlin
if (obj is Person) {
var p = obj //智能轉換
}
區間
Java
if (value >= 0 && value <= 100) {
}
for (int i = 1; i <= 100 ; i++) {}
for (int i = 1; i < 100 ; i++) {}
for (int i = 100; i >= 0 ; i--) {}
for (int i = 1; i <= 100 ; i+=2) {}
for (int i = 100; i >= 0 ; i-=2) {}
Kotlin
if (value is 0..100) {
}
for (i in 1..100 ) {}
for (i in 1 until 100) {} // 半開區間:不包含 100
for (i in 100 downTo 0) {}
for (i in 1..100 step 2) {}
for (i in 100 donwTo 1 step 2) {}
list 和 map ( 針對 Java 8 之前版本 )
Java
List<Integer> list = Arrays.asList(1, 2, 3, 4);
for(Integer value : list) {
System.out.println(value);
}
Map<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "Kotlin");
map.put(3, "iOS");
map.put(4, "React Native");
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + " , " + entry.getValue());
}
Kotlin
var list = listOf(1, 2, 3, 4);
list.forEach {
println(it)
}
var map = mapOf(1 to "Java", 2 to "Kotlin", 3 to "iOS", 4 to "React Native")
map.forEach { key, value ->
println("$key, $value")
}
// 或者
for ((key, value) in map) {
println("$key, $value")
}
開關語句
Java
int score = // some score;
String result;
switch (score) {
case 10:
case 9:
grade = "Excellent";
break;
case 8:
case 7:
case 6:
grade = "Good";
break;
case 5:
case 4:
grade = "Ok";
break;
case 3:
case 2:
case 1:
grade = "Fail";
break;
default:
grade = "Fail";
}
Kotlin
var score = // some score
var grade = when (score) {
9, 10 -> "Excellent"
in 6..8 -> "Good"
4, 5 -> "Ok"
in 1..3 -> "Fail"
else -> "Fail"
}
流水線
Java
List<String> list = Arrays.asList("java", "c++", "Android", "Kotlin", "iOS");
for(int i = 0; i < list.size(); i++ ) {
list.set(i, "Hello " + list.get(i));
if (!list.get(i).contains("c")) {
System.out.println(list.get(i));
}
}
//輸出:
// Hello java
// Hello Android
// Hello Kotlin
// Hello iOS
Kotlin
var list = arrayOf("java", "c++", "Android", "Kotlin", "iOS")
list.map {
"Hello $it"
}.filter {
!it.contains("c")
}.forEach {
println(it)
}
//輸出:
// Hello java
// Hello Android
// Hello Kotlin
// Hello iOS
函數
Java
public final void func() {}
public final int func(int value) {
return 1 * value;
}
Kotlin
fun func() {}
fun func(value: Int): Int {
return 1 * value
}
// 或者
fun func(value: Int): Int = 1 * value
類
Java
public final class Person {
private String name = null;
private int age = 25;
private Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Kotlin
class Person private constructor() {
private var name: String? = null
private var age: Int = 25
constructor (name: String, age: Int): this() {
this.name = name
this.age = age
}
}
靜態方法( 伴生對象 )
Java
public final class Manager {
private Manager() {}
public static Manager getInstance () {
return new Manager();
}
}
Kotlin
class Manager private constructor() {
companion object {
fun getInstance(): Manager = Manager()
}
}
實體類
Java
public class Person {
public String name;
public age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Kotlin
data class Person(var name: String, var age: Int)
解構
Java
Person p = new Person("haohao", 25);
String name = p.getName();
String age = p.getAge();
Kotlin
var p = Person("name", 25)
var (name, age) = p
接口
Java
interface Readable {
String getContent();
}
public final class Book implements Readable {
@override
public String getContent() {
return "Hello";
}
}
Kotlin
// Kotlin 接口中可以設置抽象和非抽象方法,可以有屬性但必須聲明爲抽象或提供訪問器實現。
interface Readable {
fun getContent(): String
fun getVersion(): Int = 0
}
class Book(): Readable {
override fun getContent(): String = "Hello"
override fun getVersion(): Int {
return super.getVersion()
}
}
繼承
Java
public class Person {
private String name = null;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello");
}
public final void sayGood() {
System.out.println("Good");
}
}
public final class Student extends Person {
private String school = null;
public Student(String name, String school) {
this.school = school;
super(name);
}
@override
public void sayHello() {
super.sayHello();
System.out.println("Hello Student");
}
}
Kotlin
open class Person(private var name: String? = null) {
open fun sayHello() = println("Hello")
fun sayGood() = println("Good")
}
class Student(private var school: String? = null, name: String): Person(name) {
override fun sayHello() {
super.sayHello()
println("Hello Student")
}
}
靜態與非靜態內部類
Java
public final class Outer {
private int bar = 100;
public static class Nester {
public final String foo() {
return "Hello Kotlin!";
}
}
public final class Inner {
public final int foo() {
return bar; // 可以訪問外部類成員
}
}
}
System.out.println(new Outer.Nester().foo());
// System.out.println(new Outer().Inner().foo()); 不能在其他類中實例化非靜態內部類
Kotlin
class Outer {
private var bar: Int = 100
// 嵌套類
class Nester {
// 不能訪問外部類成員
fun foo() = "Hello Kotlin!"
}
// 內部類
inner class Inner {
// 可以訪問外部類成員
fun foo() = bar
}
}
println(Outer.Nested().foo())
println(Outer().Inner().foo())
匿名內部類
Java
view.setOnClickListener(new OnClickListener() {
@override
onClick(View view){
// to do something.
}
});
Kotlin
interface OnClickListener {
fun onClick()
}
class View(){
var listener: OnClickListener? = null
fun setOnClickListener(listener: OnClickListener) {
this.listener = listener
}
}
view.setOnClickListener(object : OnClickListener{
override fun onClick() {
TODO("not implemented")
}
})
擴展
Java
// Java 類不能直接進行擴展
Kotlin
// 一般擴展
class MyClass {
fun foo() = println("member")
}
fun MyClass.bar() = println("extension")
MyClass().bar()
//輸出: extension
// 擴展函數與成員函數相同
class MyClass {
fun foo() = println("member")
}
fun MyClass.foo() = println("extension") // 擴展函數與成員函數相同時, 成員函數優先
fun MyClass.foo(para: Int) = println("extension")
MyClass().foo()
MyClass().foo(0)
//輸出:
// member
// extension
Kotlin Call Java
Java
public class Person {
private String name = null;
private int age = 0;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "name : " + name + ", age : " + age;
}
}
Kotlin
var p = Person()
p.name = "haohao"
p.age = 25
println(p.toString())
// name : haohao, age : 25
Java Call Kotlin
Kotlin
// Example.kt
package demo
class MyClass
fun func() {
}
Java
new demo.MyClass();
demo.ExampleKt.func();
泛型
Java
public final class Wrapper<T> {
private T item;
public Wrapper(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
Wrapper<String> wrapper = new Wrapper<>("Hello Kotlin");
System.out.println(wrapper.getItem());
Kotlin
class Wrapper<T>(val item: T)
var wrapper = Wrapper("Hello Kotlin")
println(wrapper.item)
匿名函數 ( Lambda 表達式 )
Java (Java 8)
new Thread(() -> {
System.out.println("Hello Kotlin");
}).start();
// 同下
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello Kotlin");
}
}).start();
Kotlin
Thread(Runnable {
println("Hello Kotlin")
}).start()
// Kotlin Lambda 表達式語法
val sum = {x: Int, y: Int -> x + y }
val sum1: (Int, Int) -> Int = {x, y -> x + y }
val sum2 = fun(x: Int, y: Int): Int {
return x + y
}
println(sum(2,8))
println(sum1(2,8))
println(sum2(2,8))
//輸出:
// 10
// 10
// 10
// Hello Kotlin
Kotlin 高階函數
Java
// Java 不能直接實現高階函數
Kotlin
// 高階函數,即一個函數可作爲高階函數的參數
fun superFunc(desc: String?, method: () -> String) {
print(desc)
println(method())
}
fun argFun() = "我是高階函數的參數"
//使用高階函數
superFunc("這是一個高階函數 ", ::argFun)
superFunc("這是一個高階函數 ", { argFun() })
superFunc("這是一個高階函數 ") { argFun() }
//輸出:
// 這是一個高階函數 我是高階函數的參數
// 這是一個高階函數 我是高階函數的參數
// 這是一個高階函數 我是高階函數的參數
簡單異步
Java (Java 8)
new Thread(() -> {
data = DataSource.obtain(); //耗時操作
runOnUiThread(() -> {
view.load(data); //更新 UI
});
}).start();
Kotlin (Kotlin Anko)
async {
data = DataSource.obtain(); //耗時操作
uiThread {
view.load(data); //更新 UI
}
}
泛型函數
Java
// Java 不能單獨實現泛型函數
Kotlin
fun <T> singletonList(item: T): List<T> {
return arrayListOf(item)
}
val list = singletonList<String>("kotlin")
Kotlin 內聯具體化
Kotlin
inline fun <reified T : Activity> Activity.gotoActivity() {
val intent = Intent(this, T::class.java)
this.startActivity(intent)
}
gotoActivity<NewActivity>()
Kotlin lazy 懶加載
Kotlin
val lazyValue: String by lazy {
println("init") //第一次使用時才被初始化
"Hello Kotlin"
}
fun main(args: Array<String>) {
println(lazyValue)
println(lazyValue)
}
//輸出:
// init
// Hello Kotlin
// Hello Kotlin
Kotlin observable 觀察者
Kotlin
class Person{
public var name: String by Delegates.observable("init .. "){
property,oldValue,newValue -> println("property : $property, oldValue : $oldValue, newValue : $newValue")
}
}
fun main(args: Array<String>) {
val person = Person()
println(person.name)
person.name = "haohao"
person.name = "nannan"
}
//輸出:
// init ..
// property : var Person.name: kotlin.String, oldValue : init .. , newValue : haohao
// property : var Person.name: kotlin.String, oldValue : haohao, newValue : nannan
持續更新中…
聯繫與交流
我的公衆號
我的微信