Kotlin?object的幾種用法示例詳解
1.object:匿名內部類
在Android最常用的匿名內部類之一就是點擊事件,用Java語言寫的話就是下面這樣:
public interface OnClickListener {
void onClick(View v);
}
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
}
});
上面的代碼在Kotlin中就要這么寫
interface OnClickListener {
fun onClick(v: View)
}
button.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
}
})
上面的代碼中object: View.OnClickListener就是匿名內部類的使用方式。
這里的代碼為了說明【object: 匿名內部類】的用法所以寫的比較啰嗦,如果用Lambda寫法的話可以這么寫
button.setOnClickListener {
}
上面是匿名內部類常用的一種方式,還有另一種用法就是:在繼承一個抽象類的同時還可以實現(xiàn)多個接口,直接看代碼:
interface Behavior {
fun sleep()
}
interface Characteristics {
fun gender()
}
abstract class Person {
abstract fun walk()
}
fun main() {
// 這個匿名內部類,在繼承了Person類的同時,還實現(xiàn)了Behavior(行為)、Characteristics(特征)兩個接口
val item = object : Person(), Behavior, Characteristics {
override fun sleep() {
}
override fun gender() {
}
override fun walk() {
}
}
}
對上面的代碼說明:在繼承了Person類的同時,還實現(xiàn)了Behavior(行為)、Characteristics(特征)兩個接口并分別重寫了他們的方法,這種用法靈活性比較高。
2.object: 伴生對象
Kotlin 當中沒有 static 關鍵字,所以我們沒有辦法直接定義靜態(tài)方法和靜態(tài)變量。不過,Kotlin 還是為我們提供了伴生對象,來幫助實現(xiàn)靜態(tài)方法和變量。
先看一種嵌套類的特殊情況
class Person {
object InnerSingleton {
fun foo() {}
}
}
//反編譯后的Java代碼
public final class Person {
public static final class InnerSingleton {
@NotNull
public static final Person.InnerSingleton INSTANCE;
public final void foo() {
}
private InnerSingleton() {
}
static {
Person.InnerSingleton var0 = new Person.InnerSingleton();
INSTANCE = var0;
}
}
}
由以上代碼可知定義的foo方法并不是一個靜態(tài)方法,那要如何實現(xiàn)這個靜態(tài)方法呢,可以foo方法上面加入注解@JvmStatic,這樣反編譯后foo方法就是一個靜態(tài)方法了
class Person {
object InnerSingleton {
@JvmStatic
fun foo() {}
}
}
//反編譯后的Java代碼
public final class Person {
public static final class InnerSingleton {
@NotNull
public static final Person.InnerSingleton INSTANCE;
@JvmStatic
public static final void foo() {
}
private InnerSingleton() {
}
static {
Person.InnerSingleton var0 = new Person.InnerSingleton();
INSTANCE = var0;
}
}
}
經(jīng)過這么改動Kotlin和Java的實現(xiàn)方式就都可以這么寫
Person.InnerSingleton.foo()
此時還有一個問題,foo方法的InnerSingleton有點多余,它并沒有實際意義,想直接調用Person.foo()要怎么做?
在object前面加入一個companion關鍵字即可
//Kotlin代碼
class Person {
companion object InnerSingleton {
@JvmStatic
fun foo() {
}
}
}
//反編譯后的代碼
public final class Person {
@NotNull
public static final Person.InnerSingleton InnerSingleton = new Person.InnerSingleton((DefaultConstructorMarker)null);
@JvmStatic
public static final void foo() {
InnerSingleton.foo();
}
public static final class InnerSingleton {
@JvmStatic
public final void foo() {
}
private InnerSingleton() {
}
// $FF: synthetic method
public InnerSingleton(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
加入companion就實現(xiàn)了Person.foo()的調用。companion object就是Kotlin中的伴生對象, 它其實是嵌套單例的一種也是情況。
通過上面的代碼可以得出一個結論:當伴生對象存在時如果還存在
@JvmStatic修飾的方法或者屬性,那么Kotlin編譯成Java代碼后它就會被挪到外部的類中變成靜態(tài)成員。嵌套單例是
object單例的一種特殊情況,伴身對象是嵌套單例的一種特殊情況。
3.單例模式
Kotlin中定義一個普通的單例模式非常簡單只需要在類名前面用object聲明即可
object Utils{
}
這樣就能實現(xiàn)單例,但是Java中的單例是比較復雜的,并且還有懶漢式和餓漢式之分,這樣真的就能定義嗎?
我們看一下這段代碼反編譯成Java的代碼看一看就很清楚了:
public final class Utils {
@NotNull
public static final Utils INSTANCE;
private Utils() {
}
static {
Utils var0 = new Utils();
INSTANCE = var0;
}
}
static中的代碼由虛擬機決定只會運行一次,同時在保證線程安全的前提下也保證了INSTANCE只運行一次。
但是這里有2個缺陷:
- 不支持懶加載
- 不能傳遞參數(shù),在Android中會經(jīng)常用到
context的情況,不能傳參這個用法就沒有意義
那要如何解決?
- 單例模式——借助懶加載委托
class Person(val name: String) {
}
fun main() {
val user by lazy { Person("張三") }
println("user is name ${user.name}")
}
上面的代碼使用了by lazy{ }創(chuàng)建了Person對象,而Person對象最終創(chuàng)建的時機是在println創(chuàng)建的,也就是說懶加載委托的特點就是只有在使用這個對象是才會創(chuàng)建實例。
- 單例模式—— 伴生對象 Double Check
直接看代碼,代碼是從《朱凱·Kotlin編程第一課》直接拷貝過來的
class UserManager private constructor(name: String) {
companion object {
@Volatile
private var INSTANCE: UserManager? = null
fun getInstance(name: String): UserManager =
// 第一次判空
INSTANCE ?: synchronized(this) {
// 第二次判空
INSTANCE ?: UserManager(name).also { INSTANCE = it }
}
}
}
fun main() {
// 使用
UserManager.getInstance("Tom")
}
這里首先定義了一個INSTANCE并且用private修飾這樣就可以保證不能被外界直接訪問,同時添加了@Volatile注解可以保證INSTANCE的可見性,而 getInstance() 方法當中的 synchronized,保證了 INSTANCE 的原子性。因此,這種方案還是線程安全的。
另外還要注意的一點是初始化定義的INSTANCE的默認值時null你這也就保證了只有在使用它的時候才會被實例化,也就是說實現(xiàn)懶加載的模式。
這中實現(xiàn)方式也是可以傳參的,在getInstance()方法中定義需要的屬性即可實現(xiàn)傳參
這個代碼其實跟Java的懶漢模式 + synchronized 同步鎖非常相似
public class UserManager {
private static volatile UserManager mInstance = null;
private UserManager() {
}
public static UserManager getInstance() {
if (mInstance == null) {
synchronized (UserManager.class) {
if (mInstance == null) {
mInstance = new UserManager();
}
}
}
return mInstance;
}
}
上面介紹了3中單例模式的實現(xiàn)方式,他們的使用場景如下:
- 如果單例占用內存很小并且堆內存不敏感也不需要傳參,直接使用
object即可,例如常用且無需傳參的的Utils類; - 如果單例占用內存很小并且不需要傳參,但是它的內部屬性會觸發(fā)消耗資源的網(wǎng)絡請求和數(shù)據(jù)庫查詢,這是就需要用
object搭配by lazy{ }; - 如果工程比較簡單,只有少數(shù)的單例場景、懶加載需求、需要傳遞參數(shù)就需要使用
Double Check的方式了,例如PreferenceUtils。

以上就是Kotlin object的幾種用法示例詳解的詳細內容,更多關于Kotlin object用法示例的資料請關注腳本之家其它相關文章!
相關文章
使用adb命令向Android模擬器中導入通訊錄聯(lián)系人的方法
這篇文章主要介紹了使用adb命令向Android模擬器中導入通訊錄聯(lián)系人的方法,實例分析了導入通訊錄存儲文件的技巧,需要的朋友可以參考下2015-01-01
android使用Jsoup 抓取頁面的數(shù)據(jù)
本篇文章主要介紹了android使用Jsoup 抓取頁面的數(shù)據(jù),jsoup 是一款Java的HTML解析器,有需要的朋友可以了解一下。2016-11-11
Android日期選擇器實現(xiàn)年月日三級聯(lián)動
這篇文章主要為大家詳細介紹了Android日期選擇器實現(xiàn)年月日三級聯(lián)動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
Android StatusBar 透明化方法(不同的版本適配)
本篇文章主要介紹了Android StatusBar 透明化方法(不同的版本適配),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Android帶進度條的下載圖片示例(AsyncTask異步任務)
本文主要介紹Android帶進度條的下載圖片示例(AsyncTask異步任務)的方法解析。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04

