基本型別
| 導航 語言基礎 主題: |
原始資料型別是 Java 語言中最基本的資料型別。共有 8 種:boolean、byte、char、short、int、long、float 和 double。這些型別是 Java 中資料操作的基礎。這些型別只有一種用途——儲存一種純淨、簡單的值。因為這些資料型別預設在 Java 型別系統中定義,所以它們附帶了一些預定義的操作。您不能為這些原始型別定義新的操作。在 Java 型別系統中,還有三類原始型別
- 數值型別:
short、int、long、float和double。這些原始資料型別只儲存數值資料。與這些資料型別相關的操作是 基本算術(加、減等)或 比較(大於、等於等) - 文字型別:
byte和char。這些原始資料型別儲存字元(可以是 Unicode 字母或數字)。與這些型別相關的操作是文字操作(比較兩個詞、連線字元組成詞等)。但是,byte和char也可以支援算術運算。 - 布林和空型別:
boolean和null。
所有原始型別都有固定的大小。因此,原始型別的取值範圍是有限的。較小的原始型別(byte)可以包含的值比較大的型別(long)少。
| 類別 | 型別 | 大小(位) | 最小值 | 最大值 | 精度 | 示例 |
|---|---|---|---|---|---|---|
| 整數 | byte
|
8 | -128 | 127 | 從 +127 到 -128 | byte b = 65;
|
char
|
16 | 0 | 216-1 | 所有 Unicode 字元[1] | char c = 'A';
| |
short
|
16 | -215 | 215-1 | 從 +32,767 到 -32,768 | short s = 65;
| |
int
|
32 | -231 | 231-1 | 從 +2,147,483,647 到 -2,147,483,648 | int i = 65;
| |
long
|
64 | -263 | 263-1 | 從 +9,223,372,036,854,775,807 到 -9,223,372,036,854,775,808 | long l = 65L;
| |
| 浮點型 | float
|
32 | 2-149 | (2-2-23)·2127 | 從 3.402,823,5 E+38 到 1.4 E-45 | float f = 65f;
|
double
|
64 | 2-1074 | (2-2-52)·21023 | 從 1.797,693,134,862,315,7 E+308 到 4.9 E-324 | double d = 65.55;
| |
| 其他 | boolean
|
-- | -- | -- | false, true | boolean b = true;
|
void
|
-- | -- | -- | -- | -- |
整數型別會默默地溢位
|
|
由於 Java 是強型別語言,因此您不能將浮點數(帶小數點的數字)分配給整數變數
程式碼段 3.53:將浮點數設定為 int(整數)型別的值。
int age;
age = 10.5;
|
原始型別應透過適當的值設定。原始型別可以使用字面量初始化。大多數字面量是原始型別的值,除了 字串字面量,它是 String 類的例項。
計算機科學中的數字
[edit | edit source]程式設計可能不再像以前那樣僅僅是處理大量的數字,那樣既瑣碎又枯燥。然而,如今用任何程式語言(更不用說 Java)編寫的程式碼中,大部分程式碼都在痴迷地處理數字,無論是生成巨大的質數,[2] 還是僅僅計算你踏板車的排放成本。1965 年,雙子座 5 號 太空任務險些因為一個程式設計錯誤而遭遇致命事故。[3] 1979 年,一個計算機程式高估了 5 個核反應堆抵禦地震的能力,這些反應堆暫時關閉。[4] 這兩個程式設計錯誤有一個共同點:錯誤發生時,所計算的資料是數值資料。Java 從以往的經驗中吸取教訓,為數值資料添加了改進的型別檢查,並重點強調正確識別不同型別的數值資料。在程式設計時,您必須認識到數值資料的重要性。
數字使用二進位制系統儲存在記憶體中。記憶體就像一個網格狀的單元格
每個單元格可以包含一個二進位制數(簡稱為位),也就是說,是零或一
0 |
1 |
1 |
0 |
0 |
1 |
0 |
1 |
實際上,每個單元格都包含一個二進位制位,因為一位大致相當於1,而記憶體中的空單元格表示0。單個二進位制位只能儲存兩種可能的值:零或一。
| 記憶體狀態 | 給出 | ||||||||
0 |
→ | 0 | |||||||
1 |
→ | 1 | |||||||
多個位組合在一起可以儲存多個排列——2 位可以儲存 4 個可能的值,3 位可以儲存 8 個可能的值,依此類推。例如,8 位可以儲存的最大數字(二進位制為11111111)在十進位制系統中為255。因此,數字 0 到 255 可以放在 8 位中。
| 記憶體狀態 | 給出 | ||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | 0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | 1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | 2 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | 3 |
... |
... | ||||||||
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | 255 |
一切都很好,但是透過這種方式,我們只能儲存正數(或無符號整數)。它們被稱為無符號整數。無符號整數是所有為正的整數值,不包含負值。出於這個原因,我們將要求 8 位中的一個位儲存有關數字符號(正或負)的資訊。這樣我們就只剩下 7 位可以用來計數。這些 7 位可以儲存的最大數字(1111111)在十進位制系統中為127。
正數
| 記憶體狀態 | 給出 | |||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | 0 | |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | 1 | |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | 2 | |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | 3 | |
... |
... |
... | ||||||||
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | 127 | |
負數
| 記憶體狀態 | 給出 | |||||||||
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | -128 | |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | -127 | |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | -126 | |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | -125 | |
... |
... |
... | ||||||||
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | -1 | |
總而言之,使用這種方法,8 位可以儲存從-128到127(包括零)的數字——總共 256 個數字。這應該不失為一種不錯的權衡。無符號整數的相反是有符號整數,它可以儲存正值和負值。
但是,較大的數字怎麼辦?您需要更多位來儲存較大的數字。這就是 Java 數值型別發揮作用的地方。Java 有多種數值型別——它們的大小取決於參與運算的位數。
在 Java 中,使用專門用於儲存數值資料的型別來處理數字。但是在深入研究這些型別之前,我們必須首先確立一些概念。就像你在高中(甚至小學)一樣,Java 中的數字被分為不同的組和系統。正如你現在所知道的,數字系統包括整數(0、1、2 ... ∞);負整數(0、-1、-2 ... -∞)甚至實數和有理數(圓周率值、¾、0.333~ 等)。Java 簡單地傾向於將這些數字分為兩個不同的組,整數(-∞ ... 0 ... ∞)和浮點數(任何帶小數點或分數表示的數字)。目前,我們只關注整數值,因為它們更容易理解和操作。
透過我們目前所學,我們將識別在 Java 中可建立和操作的不同型別的有符號整數值。以下是最基本數值型別的表格:整數。正如我們之前討論過的,Java 中用於整數的資料型別同時適用於正數和負數,因此它們是有符號數值型別。數值型別的大小以位為單位,它決定了最小值和最大值。如有疑問,可以隨時計算這些值。
讓我們看看這些關於 Java 中基本整數型別的新知識如何融入大局。假設您要對一年中的天數進行數值操作——所有 365 天。您會使用什麼型別?由於byte資料型別僅能達到 127,您會冒將它賦值大於其允許最大值的風險嗎?這樣的決定可能會避免您從程式程式碼中出現的可怕錯誤。對這種數值操作來說,更明智的選擇可能是short。現在,為什麼不能只建立一個數據型別來儲存所有型別的數字?讓我們來探討一下原因。
當您告訴程式您需要使用一個整數時,比如即使是byte,Java 程式也會在記憶體中分配一個空間。它會分配 8 位記憶體。雖然這對於當今擁有幾乎上萬億這樣的位空間的記憶體模組來說似乎無關緊要,但在其他情況下就很重要。一旦分配了記憶體,該部分記憶體就被使用了,只有在操作完成後才能回收。想象一個複雜的 Java 程式,您只使用long整數作為資料型別。當沒有空間進行更多記憶體分配任務時會發生什麼?您是否聽說過堆疊溢位錯誤。這就是發生的事情——您的記憶體很快就被完全用完了。所以,要謹慎選擇資料型別。
說了這麼多,讓我們看看如何建立一個數值型別。數值型別以型別名稱(short、int等)開頭,然後為記憶體中分配的空間提供一個名稱。以下是操作方法。假設我們需要建立一個變數來儲存一年中的天數。
程式碼部分 3.54:一年中的天數。
short daysInYear = 365;
|
這裡,daysInYear是儲存365作為其值的變數的名稱,而short是該特定值的的資料型別。Java 中整數資料型別的其他用法可能會看到您編寫類似以下程式碼的程式碼
程式碼部分 3.55:Java 中的整數資料型別。
byte maxByte = 127;
short maxShort = 32767;
int maxInt = 2147483647;
long maxLong = 9223372036854775807L;
|
可用於整數的資料型別是byte、short、int和long,但對於浮點數,我們使用float或double。現在我們知道了,我們可以修改程式碼部分 3.53中的程式碼,如下所示
程式碼部分 3.56:正確的浮點宣告和賦值。
double age = 10.5;
|
為什麼不是float,您可能會問?如果我們使用float,我們必須在數字後面新增f作為字尾,所以10.5應該寫成10.5f,如下所示
程式碼部分 3.57:定義float型別浮點數的正確方法。
float age = 10.5f;
|
浮點數學運算永遠不會丟擲異常。非零值除以0等於infinity。非無限值除以infinity等於0。
問題 3.7:考慮以下程式碼
問題 3.7:原始型別賦值。
...
a = false;
b = 3.2;
c = 35;
d = -93485L;
e = 'q';
|
這是五個變數。有一個long,一個byte,一個char,一個double和一個boolean。檢索每個變數的型別。
答案 3.7:原始型別賦值和宣告。
boolean a;
double b;
byte c;
long d;
char e;
a = false;
b = 3.2;
c = 35;
d = -93485L;
e = 'q';
|
a只能是boolean,因為只有 boolean 可以處理 boolean 值。e只能是char,因為只有 char 可以包含一個字元。b只能是double,因為只有 double 可以包含這裡的十進位制數。d是long,因為byte不能包含這麼小的值。c是剩下的那個,所以它是byte。
資料轉換(強制轉換)可以在兩種原始型別之間發生。強制轉換有兩種型別
- 隱式:不需要強制轉換操作;數值的大小總是保留的。但是,從整數轉換為浮點型別時,精度可能會丟失
- 顯式:需要強制轉換操作;數值的大小可能不會保留
程式碼部分 3.58:隱式強制轉換(int 轉換為 long,強制轉換不需要)。
int i = 65;
long l = i;
|
程式碼部分 3.59:顯式強制轉換(long 轉換為 int,強制轉換需要)。
long l = 656666L;
int i = (int) l;
|
下表顯示了原始型別之間的轉換,它顯示了顯式轉換的強制轉換操作
從byte |
從char |
從short |
從int |
從long |
從float |
從double |
從boolean | |
|---|---|---|---|---|---|---|---|---|
到byte |
- | (byte) | (byte) | (byte) | (byte) | (byte) | (byte) | N/A |
到char |
- | (char) | (char) | (char) | (char) | (char) | N/A | |
到short |
(short) | - | (short) | (short) | (short) | (short) | N/A | |
到int |
- | (int) | (int) | (int) | N/A | |||
到long |
- | (long) | (long) | N/A | ||||
到float |
- | (float) | N/A | |||||
到double |
- | N/A | ||||||
到boolean |
N/A | N/A | N/A | N/A | N/A | N/A | N/A | - |
與 C、C++ 和類似語言不同,Java 無法將false表示為0或null,也無法將true表示為非零。Java 無法從 boolean 強制轉換為非 boolean 原始資料型別,反之亦然。
對於非原始型別
| 到 Integer | 到 Float | 到 Double | 到 String | 到 Array | |
|---|---|---|---|---|---|
| 整數 | - | (float)x | (double)x x.doubleValue() |
x.toString() Float.toString(x) |
new int[] {x} |
| Float | java.text.DecimalFormat("#").format(x) | - | (double)x | x.toString() | new float[] {x} |
| Double | java.text.DecimalFormat("#").format(x) | java.text.DecimalFormat("#").format(x) | - | x.toString() | new double[] {x} |
| String | Integer.parseInt(x) | Float.parseFloat(x) | Double.parseDouble(x) | - | new String[] {x} |
| Array | x[0] | x[0] | x[0] | Arrays.toString(x) | - |
- ↑ 根據"STR01-J. 不要假設 Java char 完全代表 Unicode 程式碼點". 卡內基梅隆大學 - 軟體工程研究所. 檢索於 2018 年 11 月 27 日.,並非所有 Unicode 字元都適合 16 位表示
- ↑ 截至編輯(2013 年 12 月 11 日),網際網路梅森素數大搜索 專案迄今為止已將最大的素數識別為 17,425,170 位數。素數對密碼學家很有價值,因為數字越大,他們可以使用該特定數字使他們的資料加密邏輯越安全。
- ↑ 由於軟體錯誤,雙子座 5 號在計劃的太平洋著陸點以西 130 公里處著陸。地球的自轉速度被程式設計為每太陽日旋轉一次,而不是正確的值,每恆星日旋轉一次。
- ↑ 他們設計中使用的一個程式使用了變數的算術和,而它應該使用它們的絕對值的和。(Evars Witt,“小電腦和大問題”,美聯社新聞,1979 年 3 月 16 日。另見 Peter Neumann,“關於軟體正確性和社會程序的社論”軟體工程筆記,第 4 卷(2),1979 年 4 月,第 3 頁)