Java里的static在Kotlin里如何實(shí)現(xiàn)
static修飾符是java里面非常常用的一個(gè)東西,用法也非常多。然而,在kotlin里竟然沒(méi)有這個(gè)東西!那該如何替代呢?本文就總結(jié)了下java里面static的幾種常見(jiàn)用法在kotlin里的替代方式。
static在java里面的用法總結(jié)
static在java里面的用法有很多,最常用的有下面幾種:
- 靜態(tài)變量及方法
- 靜態(tài)初始化
- 靜態(tài)內(nèi)部類
下面我們就看看這幾種場(chǎng)景在kotlin是如何實(shí)現(xiàn)的。
場(chǎng)景一:靜態(tài)變量及方法
靜態(tài)變量及方法可能是我們平時(shí)用到static最多的地方,我們先看看java里面是如何做的。
java靜態(tài)變量及方法介紹:
首先,是靜態(tài)變量和方法的定義:
public class StaticTest {
public static int STATIC_VAR = 0;
public static void staticMethod(String str){
System.out.println(str);
}
}
然后是靜態(tài)變量和方法的使用:
StaticTest.STATIC_VAR = 10;
StaticTest.staticMethod("hello");
java的實(shí)現(xiàn)方式大家都非常熟悉了,下面著重說(shuō)說(shuō)kotlin是如何實(shí)現(xiàn)的。
kotlin替代靜態(tài)變量及方法的方案
kotlin通過(guò)引入“伴生對(duì)象”的概念來(lái)替代java里的靜態(tài)變量及方法。
“伴生對(duì)象”這個(gè)名詞聽(tīng)上去很古怪,其實(shí)非常簡(jiǎn)單:在類的內(nèi)容使用companion來(lái)標(biāo)記一個(gè)對(duì)象。所有需要“靜態(tài)化”的變量和方法都放在這個(gè)對(duì)象里。
下面是定義伴生對(duì)象的代碼:
class StaticTest {
companion object{//伴生對(duì)象是可以指定名字的,不過(guò)一般都省略掉。
var STATIC_VAR = 0
fun staticMethod(str: String?) {
println(str)
}
}
}
接下來(lái)看看如何使用伴生對(duì)象,伴生對(duì)象只能通過(guò)類名來(lái)訪問(wèn),使用方法和java差不多:
StaticTest.STATIC_VAR = 100
StaticTest.staticMethod("hello")
kotlin的伴生對(duì)象解決了什么問(wèn)題?
大家可能會(huì)好奇,為什么kotlin要用這么一個(gè)奇怪的方式來(lái)解決這個(gè)問(wèn)題呢?
我的理解是有兩個(gè)原因:
第一,使用伴生對(duì)象體現(xiàn)了kotlin一貫的設(shè)計(jì)理念:一切都是對(duì)象!伴生對(duì)象也是對(duì)象!而java的static,顯然和對(duì)象沒(méi)有關(guān)系。
第二,伴生對(duì)象解決了java靜態(tài)變量及方法的一個(gè)常見(jiàn)的反模式:靜態(tài)方法及變量可以通過(guò)對(duì)象的引用來(lái)訪問(wèn)。
還是拿上面的例子,java的靜態(tài)變量及方法可以通過(guò)類引用和對(duì)象引用兩種方法訪問(wèn):
//通過(guò)類引用訪問(wèn)
StaticTest.STATIC_VAR = 10;
StaticTest.staticMethod("hello");
//通過(guò)對(duì)象引用訪問(wèn)
StaticTest obj = new StaticTest();
obj.STATIC_VAR = 10;
obj.staticMethod("hello");
而通過(guò)對(duì)象引用訪問(wèn)靜態(tài)變量及方法,顯然是不合適的。但是在java里卻沒(méi)有辦法從語(yǔ)法層面避免這個(gè)問(wèn)題。
而kotlin的伴生對(duì)象只能通過(guò)類引用訪問(wèn),從語(yǔ)法的層面解決了這個(gè)問(wèn)題:
//使用類引用訪問(wèn)
StaticTest.STATIC_VAR = 100
StaticTest.staticMethod("hello")
//不能使用對(duì)象引用訪問(wèn)
val obj = StaticTest()
obj.STATIC_VAR = 100 //編譯錯(cuò)誤
obj.staticMethod("hello") //編譯錯(cuò)誤
總之,kotlin里每個(gè)新的語(yǔ)言特性,都是為了填補(bǔ)java的某一個(gè)坑。
場(chǎng)景二:靜態(tài)初始化
java里的靜態(tài)初始化可以在類加載的時(shí)候初始化一些靜態(tài)變量,比如:
public class StaticTest {
public static int STATIC_VAR = 0;
static {
STATIC_VAR = 100;
System.out.println("in static init");
}
public static void main(String[] args) {
System.out.println(StaticTest.STATIC_VAR);
}
}
上面的代碼執(zhí)行結(jié)果如下:
in static init
100
在kotlin里,因?yàn)閖ava的靜態(tài)變量及方法都是放在伴生對(duì)象里實(shí)現(xiàn)的,而伴生對(duì)象也是一個(gè)普通對(duì)象,所以可以通過(guò)伴生對(duì)象的init方法來(lái)實(shí)現(xiàn)變量的初始化,代碼如下:
class StaticTest {
companion object{//伴生對(duì)象是可以指定名字的,不過(guò)一般都省略掉。
var STATIC_VAR = 0
init {
STATIC_VAR = 100
println("in companion object init")
}
}
}
執(zhí)行代碼:
println(StaticTest.STATIC_VAR)
結(jié)果如下:
in companion object init
100
可以看到,kotlin的實(shí)現(xiàn)方式要比java的更加一致,既然大家都是對(duì)象,所以都是通過(guò)init來(lái)初始化的。而java里,非靜態(tài)變量是通過(guò)構(gòu)造函數(shù)來(lái)初始化的,而靜態(tài)變量是通過(guò)static代碼塊來(lái)初始化的,兩者很不一致。
場(chǎng)景三:靜態(tài)內(nèi)部類
java的內(nèi)部類有兩種,普通內(nèi)部類和靜態(tài)內(nèi)部類。二者的區(qū)別是前者可以訪問(wèn)外部類的變量,而后者不可以。同時(shí)普通內(nèi)部類會(huì)持有外部類的一個(gè)引用,靜態(tài)內(nèi)部類則沒(méi)有。
public class StaticTest {
private int out = 0;
class InnerClass{
public void InnerClassMethod(){
out = 100; //可以訪問(wèn)外部類的變量
}
}
static class StaticInnerClass{
public void StaticInnerClassMethod(){
out = 100; //編譯錯(cuò)誤,不可以訪問(wèn)外部類的變量
}
}
}
而kotlin的內(nèi)部類也有兩種:內(nèi)部類和嵌套類。從語(yǔ)法上說(shuō),二值的差別就是前者多一個(gè)inner修飾符。
下面是和java的比較:
- kotlin的內(nèi)部類(使用inner修飾符)相當(dāng)于java的普通內(nèi)部類,可以訪問(wèn)外部變量,同時(shí)持有外部對(duì)象的引用。
- kotlin的嵌套類(沒(méi)有inner修飾符)相當(dāng)于java的靜態(tài)內(nèi)部類,不可以訪問(wèn)外部變量
kotlin嵌套類的例子:
class StaticTest {
var out = 0
inner class InnerClass{
fun InnerClassMethod(){
out = 100 //內(nèi)部類可以訪問(wèn)外部變量
}
}
}
kotlin內(nèi)部類的例子:
class StaticTest {
var out = 0
class InnerClass{
fun InnerClassMethod(){
out = 100 //編譯錯(cuò)誤,嵌套類不可以訪問(wèn)外部變量
}
}
}
通過(guò)對(duì)比,大家應(yīng)該很容易的搞清楚kotlin里內(nèi)部類和嵌套類的區(qū)別了。
總結(jié):
本文的知識(shí)點(diǎn)總結(jié)如下:
- java的靜態(tài)變量和方法,在kotlin中使用伴生對(duì)象替代
- java的靜態(tài)初始化,在kotlin中使用伴生對(duì)象的init替代
- java的靜態(tài)內(nèi)部類,在kotlin中使用嵌套類來(lái)替代
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring @RestController注解組合實(shí)現(xiàn)方法解析
這篇文章主要介紹了Spring @RestController注解組合實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
mybatis.type-aliases-package的作用及用法說(shuō)明
這篇文章主要介紹了mybatis.type-aliases-package的作用及用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
java實(shí)現(xiàn)發(fā)送email小案例
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)發(fā)送email小案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
springboot項(xiàng)目編寫(xiě)發(fā)送異常日志到企微工具包的操作方法
本文介紹了Springboot項(xiàng)目如何編寫(xiě)發(fā)送異常日志到企業(yè)微信的工具包,內(nèi)容包括創(chuàng)建基礎(chǔ)Bean、配置類、pom依賴等步驟,并展示了如何通過(guò)nacos進(jìn)行配置,這為開(kāi)發(fā)者提供了一種有效的日志管理方案,方便快速定位和處理項(xiàng)目中的異常問(wèn)題,感興趣的朋友跟隨小編一起看看吧2024-09-09
Java利用反射對(duì)list對(duì)象做過(guò)濾
這篇文章主要介紹了Java利用反射對(duì)list對(duì)象做過(guò)濾,但是使用反射對(duì)效率有影響,但在一些特殊情況也有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-03-03
異常try?catch的常見(jiàn)四類方式(案例代碼)
這篇文章主要介紹了異常try?catch的常見(jiàn)四類方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
JAVA實(shí)現(xiàn)FTP斷點(diǎn)上傳的方法
這篇文章主要介紹了JAVA實(shí)現(xiàn)FTP斷點(diǎn)上傳的方法,涉及java使用FTP實(shí)現(xiàn)文件傳輸?shù)南嚓P(guān)技巧,需要的朋友可以參考下2015-06-06
最新SpringCloud?Stream消息驅(qū)動(dòng)講解
SpringCloud Stream 是一個(gè)構(gòu)建消息驅(qū)動(dòng)微服務(wù)的框架,通過(guò) SpringCloud Stream 連接消息中間件,以實(shí)現(xiàn)消息事件驅(qū)動(dòng),這篇文章主要介紹了SpringCloud?Stream消息驅(qū)動(dòng),需要的朋友可以參考下2022-11-11

