近期準備轉換跑道,即使是資料工程師的職缺也不全然都是用Python的,也有用Java或是用C/C++的企業。因此,想說趁著空窗期的這段時間稍微回顧一下Java的資料型態和一些邏輯。
變數
相較於Python的動態型別,Java是強型別的語言,所有變數都必須在宣告時指定型態。
1 | # 這是 Python |
1 | // 這是 Java |
記憶體區間
在Java程式執行期間,記憶體可以分為三個部分:Global、Stack、Heap。
Global
用來放全域變數、靜態變數。
Stack
Stack是由作業系統自動化管理的記憶體區塊。為了讓系統能夠清楚且有效地管理這些資源,Stack中所存放的資訊,通常在編譯的時候就能預先計算好它們的生命週期。也因為這樣,Stack主要用來存放以下這些能夠明確掌控生命週期的資料:
- 區域變數 Local Variables
- 方法的參數 Method Parameters
- 方法的回傳位址 Method Return Address
這些資料會隨著方法的執行而進入Stack,方法執行完畢後,對應的記憶體就會直接被回收,過程完全由系統自動處理,開發者不需要手動管理。
然而,Stack空間是有限的。如果一次塞入太多資料,像是遞迴沒寫好導致無限呼叫,或是方法堆疊過深,就會造成StackOverflowError,這表示Stack的記憶體被用光光啦!
Heap
能夠被預測生命週期的資料,就會放在Stack;反過來,無法預測生命週期或大小的資料,就會被放進Heap。在Java裡,只要是透過new關鍵字產生的物件,基本上都會被存進Heap裡。不過,Heap跟Stack最大的不同點在於:Heap裡的記憶體不會自動回收。換句話說,資料放進Heap之後,系統不會幫你決定什麼時候把這塊記憶體清掉,如果一直放著不用,記憶體就會越佔越多,最後可能導致系統記憶體耗盡。
幸好,Java幫我們設計了一個「垃圾回收機制(Garbage Collection, GC)」。這套機制會在程式執行過程中自動檢查:哪些物件已經不再被使用,然後主動把它們佔用的記憶體釋放出來。這樣一來,Java開發者就不用自己負責手動釋放記憶體,程式設計的負擔也少很多。
不過要注意,Heap還是有上限的。如果產生太多物件、或記憶體被撐爆,最終遇到OutOfMemoryError,告訴你Heap空間不夠用了。
小提醒:這不是資料結構裡的Heap(堆積樹)喔!
資料型態
Java 的資料型態種類有兩種:
- 基本資料型態 Primitive type
- 參考資料型態 Reference type
基本資料型態
Java 有以下八種預先定義好的資料型態:boolean, char, byte, short, int, long, float, double。
| 名稱 | 位元數 | 值 |
|---|---|---|
| boolean | true / false | |
| char | 16 | ‘\u0000’ to ‘\uFFFF’ |
| byte | 8 | -128 ~ +127 |
| short | 16 | -32768 ~ +32767 |
| int | 32 | -2147483648 ~ +2147483647 |
| long | 64 | -9223372036854775808 ~ +9223372036854775807 |
| float | 32 | -3.40292347E+38 ~ +3.40292347E+38 |
| double | 64 | -1.7976931348623157E+308 ~ +1.7976931348623157E+308 |
參考資料型態
在Java中,所有非基本資料型態的類型都屬於參考資料型態。例如:字串String、自定義的class、陣列Array、介面Interface、列舉enum…
Overload 溢位
從上表中可以看到,每個基本資料型態都有他的數值範圍,如果運算過程中超出了他可以表示的範圍,就會發生溢位。
1 | int intmax=java.lang.Integer.MAX_VALUE; |
執行結果:
1 | Max value of int : 2147483647 |
溢位是容易發生的程式錯誤,我們必須要清楚自己所處理的資料可能會到多少數值範圍,而選用適當的資料型態,或是加上檢查數值範圍的功能。
基本與參考資料型態之差異
運算子
這應該不用特別紀錄XD,這是程式設計的基礎中的基礎,下面單純做一個紀錄。
一元運算子
一元運算子只需要一個運算元
| 一元運算子 | 含義 |
|---|---|
| + | 正號 |
| - | 負號 |
| ! | NOT 否定 |
| ~ | 取 1 補數 |
算數運算子
| 算數運算子 | 含義 |
|---|---|
| + | 加法 |
| - | 減法 |
| * | 乘法 |
| / | 取商數 |
| % | 取餘數 |
關係運算子
| 關係運算子 | 含義 |
|---|---|
| > | 大於 |
| < | 小於 |
| >= | 大於等於 |
| <= | 小於等於 |
| == | 相等 |
| != | 不等於 |
遞增與遞減運算子
| 遞增與遞減運算子 | 含義 |
|---|---|
| ++ | 遞增,變數加1 |
| – | 遞減,變數減1 |
邏輯運算子
| 邏輯運算子 | 含義 |
|---|---|
| && | AND |
- &&: 兩者都為真,結果才會為真。
- ||: 只要其中一個為真,結果就會為真。
三元運算子
三元,就是要放入三個東西。
1 | 判斷式 ? 若判斷為真執行區塊 : 若判斷為假執行區塊 |
範例如下:
1 | int a = 100; |
執行結果:
1 | 100 |
仔細搞懂就會發現,他其實就是 if else 的縮寫!
1 | if(flag){ |
型態比對運算子
在寫程式的時候,有時會需要檢查某個物件是否屬於指定的類別(class)、子類別(subclass)或介面(interface)。登登登!這時候我們就需要instanceof來做判斷,他會回傳boolean。
1 | public class App { |
執行結果:
1 | true // a是A物件 |
參考:https://yubin551.gitbook.io/java-note/basic_java_programming/datatype/primitive_reference_difference