看到Android Studio 3.0會內建Kotlin,而且Google也開始以Kotlin為Android的官方語言,怎麼不來了解一下呢?畢竟Koltin 與 Java 都是跑在JVM上的語言相容性極佳,而且兩者可以同時並存,學起來百利無一害,頂多有問題再改回Java來寫,而且Java 與 Koltin之間的呼叫完全沒有問題。
類別宣告
類別宣告方式 Java 與 Koltin的不同
Java 宣告:
public class MainActivity : Activity
{
final int REQUEST_ID = 1;
static String TAG = "MainActivity";
private RecyclerView recyclerView;
public MainActivity()
{
}
@overrite
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// 變數的宣告
Button button = new Button(this);
String name = "Values";
}
}
Kotlin 宣告:
class MainActivity() : Activity() {
val REQUEST_ID : Int = 1
private lateinit var recyclerView : RecyclerView
companion object {
var TAG = "MainActivity"
}
init {
}
override fun onCreate(savedInstanceState: Bundle?) : Unit {
super.onCreate(savedInstanceState)
// 變數的宣告
var button : Button = Button(this)
var name : String? = "Values" // name 變數允許null
}
- 以建構涵式來說 class MainActivity() : Activity() 就等於 宣告MainActivity 繼承 Activity,又宣告第一個建構式 是不帶參數,建構式的內容則是以init {}的內容。所以當只有一個建構式這樣就夠了。
- Koltin 的class 預設是public,並且不允許繼承,必須加上open才可以繼承
- 以參數來說 是以 [變數名稱] : [類別型別] 來宣告,後面的 ? 代表此變數允許null
- 以函式來說 是以 [有無overrite] fun [function名稱] ([變數]) : [有無回傳值] 來宣告
- Java 的void 等同於 Kotlin 的Unit
- 每一行程式結束不需要加分號 (;)
- 變數的宣告 類似於 TypeScript,var name : String = "Values"來宣告,也可以寫成 var name = "Values"。
- Kotlin 的 val 等同於 Java 的 final就是常量
- class內的欄位宣告的同時必須要初始化,需要晚點初始化的變數需要加上lateinit關鍵字,lateinit var recyvlerView : RecyclerView。
- 不像Java需要寫Button button = new Button(this);,在Koltin只要寫 var button = Button(this),這一點我很不習慣,這樣會跟呼叫函式搞混,怎麼會這樣設計?
- Kotlin 移除 static的概念,請將靜態的東西 宣告在 companion 內部。
當如果有第二的以上建構式,則以constructor來宣告,冒號後面則可以使用 this / super
constructor(name: String) : this() {
}
資料模型類別
以data class 來宣告,將屬性宣告在建構式之中
data class ProductModel (var Name : String, var Price : Int)
等同於Java的寫法
public class ProductModel
{
String Name;
int Price;
public void SetName(String name)
{
this.Name = name;
}
public String GetName()
{
return this.Name;
}
}
擴充函式
Kotlin 擁有 Java沒有的擴充函式,有些類別別人已經寫好,你可以重新幫他加上新的方法,func 後面的String.isNullOrEmpty就是幫String新增加一個方法,有沒有看到C#的影子出現
// 不需要像c#一樣,需要定義static class,而是直接寫fun就好,剛開始也是卡在這裡很久,以為要定義class
fun String.isNullOrEmpty() : Boolean {
return this == null || this.equals("");
}
// 最後就可以這樣使用
"abc".isNullOrEmpty()
Lambda
Java 的寫法
// 原本使用匿名物件寫法
Button button = new Button(this);
button.setOnClickListener(new View.OnLongClickListener(){
@overrite
public boolean onLongClick(View v){
....
return true;
}
}
// 使用retrolambda plugin or Java8 特性後
Button button = new Button(this);
button.setOnLongClickListener((v) ->{
....
return true;
}
}
button.setOnClickListener((View v) ->{
....
return true;
}
}
Kotlin 的Lambda 是以 { } 包起來,多行的程式碼結尾需要加上分號( ; ),最後一行為回傳值
var button : Button = Button(this)
// 省略 傳入值
button.setOnLongClickListener { Log.d(TAG, "click"); true; }
// 當傳入值只有一個,可以用it代表傳入值
button.setOnLongClickListener { Log.d(TAG, "click" + it.toString()); true; }
// 宣告傳入值為 v
button.setOnLongClickListener { v -> Log.d(TAG, "click"); true; }
// 完整宣告
button.setOnLongClickListener { v : View -> Log.d(TAG, "click"); true; }
button.setOnLongClickListener { (v : View) -> Log.d(TAG, "click"); true; }
// 匿名物件的宣告
var onClick : View.OnClickListener = object : View.OnClickListener {
override fun onClick(v: View?) {
}
}
if-else、switch
Java 的 三元運算子
String name = "Values";
int length = name!= null ? name.length() : 0;
Kotlin 除了三元運算子 還有 if-else可用
var name : String? = "Values" // name 變數允許null
var length = name != null ? name.length : -1
var length1 = name?.length() ? : -1
var length2 = if(name != null) name.length() else -1 // if-else 可以有回傳值,回傳最後一行,類似lambda
Java 的 型別檢查 與 轉型
class Child : Father {}
Child c = new Father();
if( c instanceOf Father )
((Father) c).DoSomeThing();
Kotlin 的 型別檢查 與轉型
class Child() : Father() {}
var c : Child = Father()
if( c is Father )
(c as Father).DoSomeThing()
var example1 = c as Father
var example2 = c as Father?
var example3 = c as? Father
var example4 = c as? Father?
例子中给出了四种使用as的方式,下面逐行解释:
1. 将c转换为Father类型的对象,如果c不是可以转换为Father类型的对象,则会抛出异常,如果c为null,也会抛出异常;
2. 将c转换为Father?类型的对象,,如果c不是可以转换为Father类型的对象,则会抛出异常,如果c为null,则返回null
3. 将c转换为Father类型的对象,如果c不是可以转换为Father类型的对象,则返回null,如果c为null,则返回null;
4. 将c转换为Father?类型的对象,如果c不是可以转换为Father类型的对象,则返回null,如果c为null,则返回null.
总结一下,就是as?是尝试性的进行类型转换,如果能转换,则转换,不能转换,则返回null。
Java的 switch 在 Kotlin 叫 when,功能更為強大
when(x) {
is Int -> print(x + 1)
is String -> print(x.size() + 1)
is Array<Int> -> print(x.sum())
}
Kotlin 的字串模板
val apples = 4
println("I have $apples apples.")
//=========================================
val apples = 4
val bananas = 3
println("I have $apples apples and " + (apples + bananas) + " fruits.") // Java-esque
println("I have $apples apples and ${apples+bananas} fruits.") // Kotlin
Kotlin 的區間表達
// Java 的寫法
if (1 <= i && i <= 10) {
println(i)
}
if (IntRange(1, 10).contains(i)) {
println(i)
}
if (i in 1.rangeTo(10)) { ... }
if (i in 1 ... 10) { ... }
for(i in 1..4 step 2) { ... }
for (i in 4 downTo 1 step 2) { ... }