日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【对比Java学Kotlin】object 关键字

發布時間:2023/12/15 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【对比Java学Kotlin】object 关键字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

兩種用法

Kotlin 的 object 關鍵字有兩種用法,一個是作為右值表達式的前綴,一個是作為類的前綴修飾符。

object 表達式

object 表達式一般用于對現有類進行稍微修改、因為是臨時使用一次而不值得新建類完成的場景,我們稱其為匿名對象。

Any 類型的匿名對象

先來直觀感受下用法:

val o = object {val hello = "Hello"val world = "World"override fun toString(): String {return "$hello, $world"} }val r = object : Runnable {override fun run() {TODO("Not yet implemented")} }r.run()

這時 Java 同學舉手示意要發言:這個我也行呀,你看:

Object o = new Object() {String hello = "Hello";String world = "World";@Overridepublic String toString() {return hello + ", " + world;} };// 還有這種匿名對象: Runnable r = new Runnable() {@Overridepublic void run() {} };r.run();

看起來確實挺像的,但是,在 Kotlin 中我們可以隨意加其他方法,并能引用到這些方法:

val o = object {val hello = "Hello"val world = "World"override fun toString(): String {return "$hello, $world"}fun length(): Int {return toString().length} }val l = o.length() // 注意此行代碼,在 kotlin 中可以正確運行

Java:矮油,有點吊哦,我是不允許這種調用的,會直接編譯報錯:

Object o = new Object() {String hello = "Hello";String world = "World";@Overridepublic String toString() {return hello + ", " + world;}public int length() {return toString().length();} };int l = o.length(); // 編譯報錯:Cannot resolve method 'length' in 'Object'

具體類型的匿名對象

可以看出上述 object 表達式是祖先類 Any 的匿名對象。我們不僅可以對 Any,還能對某個具體的類/接口定義匿名對象,具體用法是 object 關鍵字+冒號:

window.addMouseListener(object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) { /*...*/ }override fun mouseEntered(e: MouseEvent) { /*...*/ } })

更進一步,可以在定義匿名類的時候同時實現繼承關系:

open class A(x: Int) {public open val y: Int = x }interface B { /*...*/ }val ab: A = object : A(1), B {override val y = 15 }

匿名對象做返回值

匿名對象類型除了以普通變量的形式出現,還可以當做函數的返回值:

class C {private fun getObject() = object { // private 方法,所以 printX() 方法可以引用成員變量 xval x: String = "x"}fun printX() {println(getObject().x) // 可以引用到 x} }

但是并不是所有場景下都可以引用匿名對象的成員的,如下場景是可以的:

  • 當匿名對象是局部變量時;
  • 作為成員函數返回值或成員變量出現時,成員需是 private 且不是 inline 的;
    當成員不是 private 或者是 inline是,我們無法引用到匿名對象的成員,只會把它當做未進行過修改的類型進行解析,這個類型由成員顯式聲明的類型決定:
interface A {fun funFromA() {} } interface Bclass C {// public成員方法,返回類型為 Any,無法引用到 xfun getObject() = object {val x: String = "x"}// public成員方法,返回類型為 A,無法引用到 xfun getObjectA() = object: A {override fun funFromA() {}val x: String = "x"}// public成員方法,返回類型是顯式聲明的類型 B,無法引用到方法 funFromA() 和 x// 而且這種同時存在多個基類的場景必須要顯式聲明返回類型 B,否則會報錯 Right-hand side has anonymous type. Please specify type explicitlyfun getObjectB(): B = object: A, B { override fun funFromA() {}val x: String = "x"} }

閉包

與 Java 中的匿名類一樣,Kotlin 的匿名對象也可以引用到匿名對象外部的變量,從而實現閉包的效果,而且不需要像 Java 那樣外部變量必須是 final 的:

fun countClicks(window: JComponent) {var clickCount = 0var enterCount = 0window.addMouseListener(object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) {clickCount++}override fun mouseEntered(e: MouseEvent) {enterCount++}})// ... }

object 聲明

object 關鍵字另一種用法是修飾類或者類的成員,但是不能修飾局部變量。其中最常見的是直接修飾類,這時被修飾的類就是個線程安全的單例:

object DataProviderManager {fun registerDataProvider(provider: DataProvider) {// ...}val allDataProviders: Collection<DataProvider>get() = // ... }

在 Kotlin 中使用上述單例:

DataProviderManager.registerDataProvider(...)

在 Java 中使用上述單例:

DataProviderManager.INSTANCE.registerDataProvider(...)

companion 關鍵字

當我們想像 Java static 關鍵字那樣,不借助某個具體實例來引用類的成員方法或屬性時,可以在類里面用 companion object:

interface Factory<T> {fun create(): T}class MyClass {companion object Company : Factory<MyClass> {override fun create(): MyClass = MyClass()}}val f: Factory<MyClass> = MyClassf.create()val f1: Factory<MyClass> = MyClass.Companyf1.create()

需要注意的是:

  • 類里面最多只能有一個 companion object;
  • 上述例子中的自定義名稱 Company 可以省略,不影響使用,如果省略 Company 則調用的時候可以使用 MyClass.Companion,或者直接使用 MyClass 均可,MyClass 就代指其內部的 companion object;
  • 外部類的成員可以引用 companion object 里面的成員;
  • companion object 的用法看起來跟 Java 的 static 關鍵字有點像,但是其本質上還是一個對象,上述示例中 Company 實現了 Factory 接口也印證了這一點,如果要用真正的 static 字段,需要使用 @JVMStatic 注解,且 @JVMStatic 注解只能用于 object 或 companion object 修飾的對象的成員;

表達式和聲明的區別

  • 表達式在聲明的地方就會被立即初始化和執行;
  • 聲明是延遲初始化的,即第一次被使用的時候才會初始化;

總結

以上是生活随笔為你收集整理的【对比Java学Kotlin】object 关键字的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。