最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細(xì)聊聊JDK中的反模式接口常量

 更新時(shí)間:2022年01月07日 09:20:35   作者:看山灬  
這篇文章主要給大家介紹了關(guān)于JDK中反模式接口常量的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用jdk具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前言

在實(shí)際開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)需要定義一個(gè)文件,用于存儲(chǔ)一些常量,這些常量設(shè)計(jì)為靜態(tài)公共常量(使用 public static final 修飾)。這個(gè)時(shí)候就出現(xiàn)兩種選擇:

  • 在接口中定義常量,比如 JDK 1.1 中的 java.io.ObjectStreamConstans 接口;

  • 在類中定義常量,比如 JDK 1.7 中的 java.nio.charset.StandardCharsets;

這兩種方式都能夠達(dá)到要求:存儲(chǔ)常量、無(wú)需實(shí)例化。下面分情況討論下兩種方式孰優(yōu)孰劣。

常量接口

首先從代碼的角度分析,接口中定義的變量都必須是常量,即默認(rèn)使用 public static final 修飾。也就是說(shuō),在寫代碼的時(shí)候直接寫成下面這樣:

public?interface?ObjectStreamConstants?{
????short?STREAM_MAGIC?=?(short)0xaced;
????short?STREAM_VERSION?=?5;
}

但是在類中就必須乖乖的寫成下面這種樣子:

public?final?class?ObjectStreamConstants?{
????public?static?final?short?STREAM_MAGIC?=?(short)0xaced;
????public?static?final?short?STREAM_VERSION?=?5;
}

從直觀的感受,接口寫起來(lái)方便多了。第二個(gè)問(wèn)題:因?yàn)轭愔袑懙淖址冉涌诙?,所以編譯之后文件大小也是類文件比接口文件大。第三個(gè)問(wèn)題:在JVM加載過(guò)程中,接口沒(méi)有類提供的額外特種(如重載、方法的動(dòng)態(tài)綁定等),所以接口加載比類快。分析到此,似乎沒(méi)有什么理由不用接口定義常量了。但是,BUT,這種做法卻是一種嚴(yán)重的反模式行為。引用《Effective Java》中的一段描述:

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

翻譯出來(lái)就是:

常量接口模式是對(duì)接口的不良使用。類在內(nèi)部使用某些常量,這純粹是實(shí)現(xiàn)細(xì)節(jié)。實(shí)現(xiàn)常量接口會(huì)導(dǎo)致把這樣的實(shí)現(xiàn)細(xì)節(jié)泄露到該類的導(dǎo)出API中。類實(shí)現(xiàn)常量接口,這對(duì)于類的用戶來(lái)講并沒(méi)有什么價(jià)值。實(shí)際上,這樣做反而會(huì)使他們更加糊涂。更糟糕的是,它代表了一種承諾:如果在將來(lái)的發(fā)行版本中,這個(gè)類被修改了,它不再需要使用這些常量了,它依然必須實(shí)現(xiàn)這個(gè)接口,以確保兼容性。如果非final類實(shí)現(xiàn)了常量接口,它的所有子類的命名空間也會(huì)被接口中的常量所“污染”。

這樣說(shuō)來(lái)就很明白透徹了:

  • 接口是不能阻止被實(shí)現(xiàn)或繼承的,也就是說(shuō)子接口或?qū)崿F(xiàn)中是能夠覆蓋掉常量的定義,這樣通過(guò)父、子接口(或?qū)崿F(xiàn)) 去引用常量是可能不一致的;

  • 同樣的,由于被實(shí)現(xiàn)或繼承,造成在繼承樹中可以用大量的接口、類或?qū)嵗ヒ猛粋€(gè)常量,從而造成接口中定義的常量污染了命名空間;

  • 接口暗含的意思是:它是需被實(shí)現(xiàn)的,代表著一種類型,它的公有成員是要被暴露的API,但是在接口中定義的常量還算不上API。

綜上所述:使用接口定義常量,是一種不可取的行為。JDK中定義的接口常量(例如java.io.ObjectStreamConstans)應(yīng)該算是反面教材。

類接口

既然使用接口第一常量不可取,那就只能通過(guò)類定義常量了。雖然在JAVA中類不能夠多繼承,但是子類也能夠“污染”父類定義常量的命名空間。所以為了常量不可變,需要將常量類定義為final的,然后再?gòu)氐c(diǎn)就是再定義個(gè)private的構(gòu)造函數(shù)。就像java.nio.charset.StandardCharsets一樣:

public?final?class?StandardCharsets?{
????private?StandardCharsets()?{
????????throw?new?AssertionError("No?java.nio.charset.StandardCharsets?instances?for?you!");
????}
????public?static?final?Charset?US_ASCII?=?Charset.forName("US-ASCII");
????public?static?final?Charset?ISO_8859_1?=?Charset.forName("ISO-8859-1");
????public?static?final?Charset?UTF_8?=?Charset.forName("UTF-8");
}

java.nio.charset.StandardCharsets中,為了阻止各種形式的實(shí)例化,甚至在構(gòu)造函數(shù)中拋出錯(cuò)誤,也是做個(gè)夠徹底的了。

枚舉類型

但是,BUT,還有一種情況,比如常量中定義性別:男、女,使用上面的類常量,需要寫成:

public?final?class?Gender?{
????private?Gender()?{
????????throw?new?AssertionError("No?x.y.z.Gender?instances?for?you!");
????}
????public?static?final?int?MALE?=?1;
????public?static?final?int?FEMALE?=?0;
}

因?yàn)槎x的性別類型實(shí)際是int,如果手賤寫成m.setGender(3)也是沒(méi)有錯(cuò)誤的,那3又是什么鬼?是不是還要有4、56、7?那這種常量定義就失去價(jià)值了。對(duì)于這種可以歸類的常量,最好的常量定義方法應(yīng)該就是枚舉了:

public?enum?Gender?{
????MALE,?
????FEMALE
}

根據(jù)編輯的字節(jié)碼,Gender實(shí)際是:

public?final?class?Gender?extends?java.lang.Enum?{
????public?static?final?Gender?MALE;
????public?static?final?Gender?FEMALE;
}

這樣對(duì)于接受 Gender 類型參數(shù)的方法就只能傳入 MALE 或 FEMALE 了,不再有其他選項(xiàng),這就是枚舉的意義。在后來(lái)的JDK中,也出現(xiàn)了像java.nio.file.StandardOpenOption等的枚舉定義。而且枚舉的定義也不只局限于這種,還有很多其他復(fù)雜定義,可以適用各種情況,以后再慢慢討論。

結(jié)束語(yǔ)

定義常量不要使用接口常量,要在類中定義,最好是final類,并且定義private的構(gòu)造方法,如果常量可以進(jìn)行歸類,最好使用枚舉定義:枚舉 > 類 > 接口。

到此這篇關(guān)于JDK中反模式接口常量的文章就介紹到這了,更多相關(guān)JDK反模式接口常量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot + swagger 實(shí)例代碼

    springboot + swagger 實(shí)例代碼

    本篇文章主要介紹了springboot + swagger 實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • 詳解MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn))

    詳解MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn))

    這篇文章主要詳細(xì)介紹了MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn)),文中通過(guò)代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • Java基本數(shù)據(jù)類型存儲(chǔ)在JVM中的存儲(chǔ)位置介紹

    Java基本數(shù)據(jù)類型存儲(chǔ)在JVM中的存儲(chǔ)位置介紹

    這篇文章主要介紹了Java基本數(shù)據(jù)類型存儲(chǔ)在JVM中的存儲(chǔ)位置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    這篇文章主要介紹了java采集京東的全國(guó)區(qū)劃數(shù)據(jù)示例,保存成json形式,如想轉(zhuǎn)換到數(shù)據(jù)庫(kù)只需反序列化為對(duì)象保存到數(shù)據(jù)庫(kù)即可
    2014-03-03
  • Java設(shè)計(jì)模式之單例模式實(shí)例詳解【懶漢式與餓漢式】

    Java設(shè)計(jì)模式之單例模式實(shí)例詳解【懶漢式與餓漢式】

    這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式,簡(jiǎn)單說(shuō)明了單例模式的原理并結(jié)合具體實(shí)例形式分析了單例模式中懶漢式與餓漢式的具體實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2017-09-09
  • Java框架設(shè)計(jì)靈魂之反射的示例詳解

    Java框架設(shè)計(jì)靈魂之反射的示例詳解

    反射就是把Java類中的各個(gè)成員映射成一個(gè)個(gè)的Java對(duì)象。本文將通過(guò)示例為大家詳細(xì)講解Java框架設(shè)計(jì)的靈魂:反射,感興趣的可以了解一下
    2022-06-06
  • IntelliJ IDEA使用SVN分支的簡(jiǎn)單介紹

    IntelliJ IDEA使用SVN分支的簡(jiǎn)單介紹

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA使用SVN分支的簡(jiǎn)單介紹,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程

    Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程

    本文詳細(xì)講解了Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • 升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒(méi)有升過(guò)級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下
    2021-07-07
  • SpringBoot實(shí)現(xiàn)動(dòng)態(tài)配置及項(xiàng)目打包部署上線功能

    SpringBoot實(shí)現(xiàn)動(dòng)態(tài)配置及項(xiàng)目打包部署上線功能

    本文講解的是如何使用Spring動(dòng)態(tài)配置文件,實(shí)現(xiàn)不同環(huán)境不同配置,靈活切換配置文件;以及講述了如何使用?Maven?打包,然后上傳至Linux服務(wù)器進(jìn)行部署,對(duì)SpringBoot打包部署上線過(guò)程感興趣的朋友一起看看吧
    2022-10-10

最新評(píng)論

绥滨县| 武定县| 社旗县| 佛山市| 宣化县| 岑巩县| 兴宁市| 四子王旗| 广安市| 拉萨市| 巴塘县| 长乐市| 思南县| 正镶白旗| 库伦旗| 鄂托克旗| 沙洋县| 武汉市| 莱州市| 大悟县| 石渠县| 台前县| 南通市| 太仆寺旗| 浮梁县| 永和县| 宾川县| 新建县| 建宁县| 呼伦贝尔市| 铜鼓县| 嘉义市| 修文县| 唐海县| 西充县| 民县| 商南县| 哈尔滨市| 驻马店市| 股票| 无为县|