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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

尝试Java,从入门到Kotlin(上)

發(fā)布時間:2023/11/27 生活经验 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 尝试Java,从入门到Kotlin(上) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前一直使用C#開發(fā),最近由于眼饞Java生態(tài)環(huán)境,并借著工作服務化改造的契機,直接將新項目的開發(fā)都轉到Java上去。積攢些Java開發(fā)經(jīng)驗,應該對.NET開發(fā)也會有所啟發(fā)和益處。
從理論上說,Java和C#語言差別不大,畢竟難聽地說,C#就是抄Java出來的。程序語言簡史如是介紹這兩種語言:

然而隨著時間流逝語言發(fā)展,個人認為,C#在語言層面已經(jīng)大大領先了Java。關于Java和C#的比較這幾篇文章http://blog.zhaojie.me/2010/04/why-java-sucks-and-csharp-rocks-1-thoughts-and-goals.html有著詳細的描述。下面我總結一下我在趟過的坑,以供轉型或學習的同學參考。

本文并非要比出這些語言誰優(yōu)誰劣。有時候,好或壞是非常主觀的判斷,不同人有著不同的看法,強行斷定好壞只會引起無畏的爭論。這些語言有著各自的特點,有各自適合的場景。就像下面要談到的Checked Exception特性,這是個很好的特性,但是在一些情況下也會引起不少麻煩。

Checked Exception

Java是Checked Exception的。這就是說,如果你寫了一個方法,這個方法會拋出一些異常,那么你需要用throws關鍵字標明這個方法會拋出哪些異常。這個特性很難說是好還是不好。Checked Exception本質上是一種類型系統(tǒng),它明確規(guī)定了一個方法除了返回值類型以外,還可能拋出什么異常。這樣調用方函數(shù)就能夠明確地知曉應該處理或者傳遞哪些異常。這個特性在用得好的人手里,對正確處理各種邊邊角角的異常十分有用。然而,如果在你無法自己選隊友,無法控制開發(fā)人員的水平的情況下,你很可能會發(fā)現(xiàn),所有的方法都被標記為throws Exception

Lambda,以及與Checked Exception產(chǎn)生的奇怪反應

Java的Lambda本質上仍然是一個對象。事實上,Java的Lambda函數(shù)是一個滿足Functional Interface接口的對象。比如下面代碼,聲明了一個具有一個int參數(shù),返回一個int參數(shù)的函數(shù)。

@FunctionalInterface
interface AFunction {int invokeBalaBala(int a);
}

我們可以這樣定義一個這個函數(shù)的變量:AFunction f = x -> 2 * x;

Java的Lambda和Checked Exception結合在一起后,產(chǎn)生了一個非常棘手的問題。由于Checked Exception是類型系統(tǒng)的一部分,一個不拋出異常的函數(shù)和一個會拋出異常的函數(shù),它們的類型是不相同的。這就導致了Java的Lambda泛用性大大減少而且不是很好用。以對List的map操作為例,我們可以用如下代碼將list里的每個元素翻倍:

list = list.stream().map(x -> 2 * x).collect(Collectors.toList());

這里map接收一個類型為輸入一個int參數(shù),返回一個int值的函數(shù)。然而,如果我們需要給它的函數(shù)有可能拋出異常,比如這個函數(shù)會去讀取文件、訪問網(wǎng)絡服務、或者做Json反序列化,則由于類型不同,Java編譯器將會報錯。

// 這個編譯器會報錯
list.stream().map(x -> JsonUtil.parse(x)).collect(Collectors.toList());

解決方案一種是在函數(shù)體中使用try cache處理異常。但是很多時候,異常沒辦法在這個時刻處理,必須要拋出。那么還有另一種方案:將異常轉換為RuntimeExceptionRuntimeException是所謂的Unchecked Exception,它不是類型系統(tǒng)的一部分,不需要用throws標注,所以不會導致函數(shù)類型變化。另一方面,編譯器也無法檢測出是否可能會拋出RuntimeException。無論采用哪種方案,都使得這個Lambda函數(shù)變得沒那么好看。

泛型

Java的泛型原理和C#不同。C#是運行時泛型,在程序運行的時候仍然能獲取泛型的類型信息。而Java的泛型是類型擦除(Type Erasure)式泛型。名稱聽起來很高大上,意思是Java的泛型僅僅用于編譯時類型檢查,類型檢查完成后,類型信息就被編譯器擦除。在最后生成的字節(jié)碼中中,泛型類型都被改為Object類型。
比如這句:

HashMap<TK, TV> map = new HashMap<TK, TV>();

編譯后變成:

HashMap map = new HashMap();

Type Erasure方式的影響主要有兩個:

  • 運行時無法判斷類型;
  • 運行時無法動態(tài)生成泛型具現(xiàn)化的類的實例。

像下面兩句:

x instanceof T
new T()

在Java中都會編譯出錯。而這在C#中都是很常見的代碼。在C#中,我們可以有這樣的Json反序列化方法:

T parse<T>(string jsonStr)

這個方法將jsonStr反序列化為類型T的一個對象。這種寫法看起來十分自然。然而在Java中無法實現(xiàn)。因為在parse方法中需要在運行時實例化T的一個對象,而Java在運行時這些泛型都已經(jīng)被擦除,無法獲取類型T的信息,從而無法實例化。要在Java實現(xiàn)類似的方法,需要額外將一個Class對象放到參數(shù):

T parse(String jsonStr, Class<T> type)

這樣Java才能使用這個type,在運行時使用反射的方式生成類型T的實例。

Getter/Setter

在面向對象哲學中,字段屬于實現(xiàn)細節(jié),應該設為private使它隱藏在類的內(nèi)部。但是在實際中,有很多字段需要直接訪問和修改。從功能實現(xiàn)上講,直接把字段設為public也是可以的。但是這樣做的壞處在于未來功能擴展時,這個字段的含義、存儲方式可能發(fā)生變化,導致每個使用了這個字段的代碼都需要修改。因此,應該將字段的訪問封裝的方法中,即使只是很簡單的訪問和設置,也應該實現(xiàn)getter方法和setter方法。

C#和Python有property特性支持快速定義和調用getter方法和setter方法。Ruby則依靠函數(shù)調用可以省略括號的特性,使getter方法看起來很像直接訪問字段。Java沒有使用特性支持getter和setter方法,而是約定必須實現(xiàn)字段名前加get的getter方法(然而這里有個不一致的地方,如果字段是布爾類型,則加is)和字段名前加set的setter方法。這導致的一個問題是開發(fā)時需要編寫大量的getter方法和setter方法。為Java冗長的特點貢獻了一份力量。遵循這個規(guī)范很重要,以為在很多常用庫,比如Json序列化,會以getter方法作為字段存在的依據(jù)。

為了減少開發(fā)工作量,可以使用IDE自動生成getter方法和setter方法。常見的Java IDE都支持自動生成getter方法和setter方法。另一個方案是使用Lombok,通過DataGetterSetter等注解,讓編譯器在編譯時自動生成getter方法和setter。

轉載于:https://www.cnblogs.com/skabyy/p/10049106.html

總結

以上是生活随笔為你收集整理的尝试Java,从入门到Kotlin(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。