1. Kotlin的Unit 和 Java的void 的區別
// Java
public void sayHello() {System.out.println("Hello!")
}// Kotlin
fun sayHello(): Unit {println("Hello!")
}
Unit 和 Java 的 void 真正的區別在于,void 是真的表示什么都不返回,而 Kotlin 的 Unit 卻是一個真實存在的類型:
//Unit的源碼,這表明它是一個object單例類
public object Unit {override fun toString() = "kotlin.Unit"
}
2. 省略Unit,Kotlin會自動補上
一個完整的”無返回值“的函數寫法如下,即返回類型為Unit,函數最后return Unit
fun sayHello() : Unit {println("Hello!")return Unit
}
當函數返回類型是Unit時,我們是可以省略掉函數的返回類型的,因為 Kotlin 也會幫我們自動加上
fun sayHello() {println("Hello!")return Unit
}
return 我們一樣可以省略不寫,Kotlin 也會幫我們自動加上
fun sayHello() : Unit {println("Hello!")
}
這兩個 Unit 是不一樣的,上面的是 Unit 這個類型,下面的是 Unit 這個單例對象。這個并不是 Kotlin 給 Unit 的特權,而是 object 本來就有的語法特性
包括你也可以這樣寫:
val unit: Unit = Unit
因此全都省略的情況,實際上就是返回類型為Unit,并且最后一行返回了Unit這個單例對象
fun sayHello() {println("Hello!")
}
3. Unit總結
所以在結構上,Unit 并沒有任何的特別之處,它就只是一個 Kotlin 的 object 而已。
它的特殊之處,更多的是在于語義和用途的角度:它是個由官方規定出來的、用于「什么也不返回」的場景的返回值類型。但這只是它被規定的用法而已,而本質上它真就是個實實在在的類型。
也就是在 Kotlin 里,并不存在真正沒有返回值的函數,所有「沒有返回值」的函數實質上的返回值類型都是 Unit,而返回值也都是 Unit 這個單例對象,這是 Unit 和 Java 的 void 在本質上的不同。
4. Unit 的價值所在
意義就在于,Unit 去掉了無返回值的函數的特殊性,消除了有返回值和無返回值的函數的本質區別,這樣很多事做起來就會更簡單了。
比如在 Java 里面,由于 void 并不是一種真正的類型,所以任何有返回值的方法在子類里的重寫方法也都必須有返回值,而不能寫成 void,不管你用不用泛型都是一樣的:
public abstract class Maker {public abstract Object make();
}public class AppleMaker extends Maker {// 合法@Overridepublic Apple make() {return new Apple();}
}public class NewWorldMaker extends Maker {// 非法@Overridepublic void make() {world.refresh();}
}
泛型:
public abstract class Maker<T> {public abstract T make();
}public class AppleMaker extends Maker<Apple> {// 合法Overridepublic Apple make() {return new Apple();}
}public class NewWorldMaker extends Maker<void> {// 非法Overridepublic void make() {world.refresh();}
}
你只能去寫一行 return null 來手動實現接近于「什么都不返回」的效果:
public class NewWorldMaker extends Maker {@Overridepublic Object make() {world.refresh();return null;}
}
而且如果你用的是泛型,可能還需要用一個專門的虛假類型來讓效果達到完美:
public class NewWorldMaker extends Maker<Void> {@Overridepublic Void make() {world.refresh();return null;}
}
而在 Kotlin 里,Unit 是一種真實存在的類型,所以直接寫就行了(這里還借助了Kotlin自動補上Unit類型 和 最后一行自動返回Unit單例對象):
abstract class Maker {abstract fun make(): Any
}class AppleMaker : Maker() {override fun make(): Apple {return Apple()}
}class NewWorldMaker : Maker() {override fun make() {world.refresh()}
}
泛型:
abstract class Maker<T> {abstract fun make(): T
}class AppleMaker : Maker<Apple>() {override fun make(): Apple {return Apple()}
}class NewWorldMaker : Maker<Unit>() {override fun make() {world.refresh()}
}
這就是 Unit 的去特殊性,或者說通用性所給我們帶來的便利。
5. 延伸:當做純粹的單例對象來使用
所以如果你什么時候想「隨便拿個對象過來」,或者「隨便拿個單例對象過來」,也可以使用 Unit,它和你自己創建一個 object 然后去使用,效果是一樣的。
參考文章:
Unit 為啥還能當函數參數?面向實用的 Kotlin Unit 詳解