基本數據類型:Java世界的基礎積木

當我們用Java編寫程序時,首先要學會如何表示現實世界中的數據。就像我們用不同容器裝水、裝米、裝汽油一樣,Java為不同類型的數據設計了不同的"容器"——這就是數據類型。今天我們從最基礎的8種基本數據類型開始學起,它們是Java編程的"原子積木"。

整數類型:沒有小數點的數字

整數類型用於存儲不帶小數點的數字,Java提供了4種整數類型,它們的區別主要在於內存佔用大小表示範圍

表格

複製

類型

內存佔用

表示範圍

應用場景

byte

1字節

-128 ~ 127

節省內存的小整數,如文件流、網絡數據傳輸

short

2字節

-32768 ~ 32767

較少使用,主要用於兼容性場景

int

4字節

-2^31 ~ 2^31-1

默認整數類型,如年齡、數量等常規整數

long

8字節

-2^63 ~ 2^63-1

大整數,如時間戳、身份證號等

💡 內存佔用小知識:1字節=8位二進制數,所以byte類型能表示2^8=256個數字(從-128到127)。記住int是默認類型,當需要表示超過int範圍的整數時,要在數字後加L(如10000000000L)。

下面是整數類型的代碼示例,我們可以在昨天搭建的VS Code環境中創建一個DataTypeDemo.java文件來測試:

複製

public class DataTypeDemo {
    public static void main(String[] args) {
        // 整數類型示例
        byte age = 25; // 年齡用byte足夠,因為人年齡很少超過127歲
        short temperature = -15; // 温度用short,能表示-32768到32767的範圍
        int population = 1400000000; // 中國人口用int剛好
        long distance = 9460730472580800L; // 一光年的距離,必須加L表示long類型

        // 輸出各變量值
        System.out.println("年齡:" + age);
        System.out.println("温度:" + temperature + "℃");
        System.out.println("人口:" + population);
        System.out.println("一光年距離:" + distance + "米");
    }
}

浮點類型:帶小數點的數字

當需要表示帶小數點的數字(如身高1.75米、體重62.5公斤)時,就需要用到浮點類型。Java提供兩種浮點類型:

表格

複製

類型

內存佔用

精度

應用場景

float

4字節

約6-7位小數

內存緊張的場景,如遊戲圖形數據

double

8字節

約15-17位小數

默認浮點類型,如科學計算、金融數據

⚠️ 注意:float類型的數字後必須加F(如3.14F),否則會被當作double處理。double是默認浮點類型,大多數情況下推薦使用double,因為它精度更高。

浮點類型代碼示例:

複製

public class FloatDemo {
    public static void main(String[] args) {
        float piFloat = 3.1415926F; // 注意加F
        double piDouble = 3.141592653589793; // 默認double類型

        System.out.println("float類型圓周率:" + piFloat); // 輸出約3.1415925
        System.out.println("double類型圓周率:" + piDouble); // 輸出更精確的3.141592653589793

        // 浮點運算注意事項:可能存在精度問題
        double result = 0.1 + 0.2;
        System.out.println("0.1 + 0.2 = " + result); // 輸出0.30000000000000004而非0.3
    }
}

💡 為什麼0.1+0.2不等於0.3? 因為計算機用二進制存儲小數,有些十進制小數(如0.1)無法精確表示,會產生微小誤差。金融計算時應使用BigDecimal類避免此問題,這會在後續課程講到。

字符類型:單個文字符號

char類型用於存儲單個字符,佔用2字節,採用Unicode編碼,能表示包括中文在內的全球文字:

複製

public class CharDemo {
    public static void main(String[] args) {
        char letter = 'A'; // 英文字母
        char chinese = '中'; // 中文字符
        char emoji = '\uD83D\uDE0A'; // 笑臉emoji的Unicode編碼

        System.out.println("字母:" + letter); // 輸出A
        System.out.println("中文:" + chinese); // 輸出中
        System.out.println("表情:" + emoji); // 輸出😊
    }
}

💡 Unicode小知識:每個字符都有唯一的Unicode編碼,如'A'是65,'中'是20013。可以用(int)chinese查看字符的Unicode值。

布爾類型:真或假

boolean類型只有兩個值:true(真)和false(假),主要用於條件判斷,佔用1字節:

複製

public class BooleanDemo {
    public static void main(String[] args) {
        boolean isJavaFun = true;
        boolean isFishFly = false;

        System.out.println("Java有趣嗎?" + isJavaFun); // 輸出true
        System.out.println("魚會飛嗎?" + isFishFly); // 輸出false

        // 布爾值常用於條件判斷
        if (isJavaFun) {
            System.out.println("繼續學習Java吧!"); // 因為isJavaFun是true,所以會執行
        }
    }
}

變量與常量:數據的容器與固定值

變量:可以改變的量

變量就像一個貼了標籤的盒子,我們可以把數據放進去,也可以隨時更換盒子裏的數據。定義變量的語法是:數據類型 變量名 = 初始值;

複製

public class VariableDemo {
    public static void main(String[] args) {
        // 聲明變量並初始化
        int score = 85;
        String name = "小明"; // String是引用類型,後面課程會講

        System.out.println(name + "的成績是:" + score); // 輸出:小明的成績是:85

        // 修改變量值
        score = 92;
        System.out.println("修改後的成績:" + score); // 輸出:修改後的成績:92

        // 先聲明後初始化
        double height; // 聲明變量
        height = 1.75; // 初始化變量
        System.out.println("身高:" + height + "米"); // 輸出:身高:1.75米
    }
}

📝 變量命名規則

  1. 只能包含字母、數字、下劃線(_)和美元符號($)
  2. 不能以數字開頭
  3. 不能使用Java關鍵字(如int、class、if等)
  4. 區分大小寫(score和Score是兩個不同變量)
  5. 建議使用駝峯命名法:如studentName、userAge

常量:固定不變的值

常量是程序運行過程中不能改變的值,用final關鍵字聲明:final 數據類型 常量名 = 值;

複製

public class ConstantDemo {
    public static void main(String[] args) {
        // 聲明常量,常量名通常全大寫,多個單詞用下劃線連接
        final double PI = 3.1415926535;
        final int MAX_SCORE = 100;

        System.out.println("圓周率:" + PI);
        System.out.println("滿分:" + MAX_SCORE);

        // 嘗試修改常量會編譯錯誤
        // PI = 3.14; // 此行代碼會報錯:無法為最終變量PI分配值
    }
}

💡 什麼時候用常量? 當某個值在程序中多次使用且不會改變時(如圓周率、税率、配置參數),應該定義為常量。這樣不僅提高可讀性,還方便維護(修改一處即可)。

運算符:數據的加工工具

運算符用於對數據進行運算處理,Java提供了豐富的運算符,我們可以按功能分為以下幾類:

算術運算符

用於基本的數學運算:

表格

複製

運算符

作用

示例

結果

+

加法

5 + 3

8

-

減法

5 - 3

2

*

乘法

5 * 3

15

/

除法

5 / 3

1(整數相除取整)

%

取餘(模運算)

5 % 3

2

++

自增

int a=5; a++

a變為6

--

自減

int b=5; b--

b變為4

代碼示例:

複製

public class ArithmeticDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 3;

        System.out.println("a + b = " + (a + b)); // 13
        System.out.println("a - b = " + (a - b)); // 7
        System.out.println("a * b = " + (a * b)); // 30
        System.out.println("a / b = " + (a / b)); // 3(整數相除)
        System.out.println("a % b = " + (a % b)); // 1(10除以3餘1)

        // 自增自減運算符
        int c = 5;
        c++; // 等價於 c = c + 1
        System.out.println("c++ = " + c); // 6

        int d = 5;
        ++d; // 等價於 d = d + 1
        System.out.println("++d = " + d); // 6

        // 前置++和後置++的區別
        int e = 5;
        int f = e++; // 先賦值再自增:f=5, e=6
        System.out.println("e++賦值給f後:e=" + e + ", f=" + f);

        int g = 5;
        int h = ++g; // 先自增再賦值:g=6, h=6
        System.out.println("++g賦值給h後:g=" + g + ", h=" + h);
    }
}

賦值運算符

用於給變量賦值,最基本的是=,還有複合賦值運算符:

表格

複製

運算符

等價於

示例

等價於

=

-

a = 5

a = 5

+=

加後賦值

a += 3

a = a + 3

-=

減後賦值

a -= 3

a = a - 3

*=

乘後賦值

a *= 3

a = a * 3

/=

除後賦值

a /= 3

a = a / 3

%=

取餘後賦值

a %= 3

a = a % 3

代碼示例:

複製

public class AssignmentDemo {
    public static void main(String[] args) {
        int a = 10;
        a += 5; // a = a + 5 → 15
        System.out.println("a += 5: " + a);

        a -= 3; // a = a - 3 → 12
        System.out.println("a -= 3: " + a);

        a *= 2; // a = a * 2 → 24
        System.out.println("a *= 2: " + a);

        a /= 4; // a = a / 4 → 6
        System.out.println("a /= 4: " + a);

        a %= 5; // a = a % 5 → 1
        System.out.println("a %= 5: " + a);
    }
}

比較運算符

用於比較兩個值,返回boolean類型結果(true或false):

表格

複製

運算符

作用

示例

結果

==

等於

5 == 3

false

!=

不等於

5 != 3

true

>

大於

5 > 3

true

<

小於

5 < 3

false

>=

大於等於

5 >= 5

true

<=

小於等於

3 <= 1

false

代碼示例:

複製

public class ComparisonDemo {
    public static void main(String[] args) {
        int x = 5;
        int y = 8;

        System.out.println("x == y: " + (x == y)); // false
        System.out.println("x != y: " + (x != y)); // true
        System.out.println("x > y: " + (x > y)); // false
        System.out.println("x < y: " + (x < y)); // true
        System.out.println("x >= 5: " + (x >= 5)); // true
        System.out.println("y <= 7: " + (y <= 7)); // false

        // 比較字符串內容要用equals()方法,不能直接用==
        String str1 = "hello";
        String str2 = new String("hello");
        System.out.println("str1 == str2: " + (str1 == str2)); // false(比較地址)
        System.out.println("str1.equals(str2): " + str1.equals(str2)); // true(比較內容)
    }
}

⚠️ 注意:==對於基本類型比較的是值,對於引用類型(如String)比較的是內存地址。比較字符串內容應該使用equals()方法。

邏輯運算符

用於連接多個條件,進行邏輯判斷:

表格

複製

運算符

作用

特點

示例

結果

&&

邏輯與

兩邊都為true才返回true,短路特性

true && false

false

||

邏輯或

至少一邊為true就返回true,短路特性

true || false

true

!

邏輯非

取反

!true

false

&

邏輯與(不短路)

兩邊都執行,不短路

true & false

false

|

邏輯或(不短路)

兩邊都執行,不短路

true | false

true

^

邏輯異或

兩邊結果不同才返回true

true ^ false

true

💡 短路特性:對於&&,如果左邊為false,右邊就不再執行;對於||,如果左邊為true,右邊就不再執行。這可以提高效率,也可能導致右邊代碼不執行,需要注意。

代碼示例:

複製

public class LogicDemo {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;

        // 邏輯與 &&
        System.out.println("a && b: " + (a && b)); // false

        // 邏輯或 ||
        System.out.println("a || b: " + (a || b)); // true

        // 邏輯非 !
        System.out.println("!a: " + !a); // false

        // 短路特性演示
        int num = 10;
        // &&左邊為false,右邊的num++不會執行
        boolean result1 = (num > 20) && (num++ > 5);
        System.out.println("result1: " + result1 + ", num: " + num); // false, 10

        // ||左邊為true,右邊的num++不會執行
        boolean result2 = (num < 20) || (num++ > 5);
        System.out.println("result2: " + result2 + ", num: " + num); // true, 10

        // 不短路的&和|會執行兩邊
        int num2 = 10;
        boolean result3 = (num2 > 20) & (num2++ > 5);
        System.out.println("result3: " + result3 + ", num2: " + num2); // false, 11
    }
}

運算符優先級

當一個表達式中有多個運算符時,Java會按照一定的優先級進行計算。記住以下優先級規則(從高到低):

  1. 括號 ()
  2. 自增自減 ++ --
  3. 算術運算符 * / % + -
  4. 比較運算符 > < >= <= == !=
  5. 邏輯運算符 ! && ||
  6. 賦值運算符 = += -= *= /= %=

💡 最佳實踐:不確定優先級時,使用括號()明確運算順序,提高代碼可讀性。

示例:

複製

public class PriorityDemo {
    public static void main(String[] args) {
        // 優先級示例
        int result1 = 3 + 4 * 2; // 先乘後加 → 3 + 8 = 11
        System.out.println("3 + 4 * 2 = " + result1);

        int result2 = (3 + 4) * 2; // 括號改變優先級 → 7 * 2 = 14
        System.out.println("(3 + 4) * 2 = " + result2);

        boolean result3 = 5 > 3 && 2 > 1; // 先比較後邏輯與 → true && true = true
        System.out.println("5 > 3 && 2 > 1: " + result3);

        boolean result4 = 5 > 3 || 2 > 5 && 1 > 0; // &&優先級高於|| → true || false = true
        System.out.println("5 > 3 || 2 > 5 && 1 > 0: " + result4);
    }
}

類型轉換:不同類型數據的橋樑

Java是強類型語言,不同類型的數據不能直接運算,需要進行類型轉換。類型轉換分為兩種:自動類型轉換和強制類型轉換。

自動類型轉換(隱式轉換)

當把小範圍類型的數據賦值給大範圍類型的變量時,Java會自動完成轉換,這稱為自動類型轉換。就像小杯子的水可以倒進大杯子,不會溢出。

基本數據類型的轉換順序(從低到高):
byte → short → int → long → float → double
char → int(char可以自動轉換為int,因為char本質是Unicode編碼值)

代碼示例:

複製

public class AutoCastDemo {
    public static void main(String[] args) {
        // byte → int
        byte b = 100;
        int i = b; // 自動轉換,無需額外操作
        System.out.println("byte轉int: " + i); // 100

        // int → long
        int num = 1000;
        long l = num; // 自動轉換
        System.out.println("int轉long: " + l); // 1000

        // long → double
        long bigNum = 123456789L;
        double d = bigNum; // 自動轉換
        System.out.println("long轉double: " + d); // 123456789.0

        // char → int
        char c = 'A'; // 'A'的Unicode值是65
        int charValue = c;
        System.out.println("'A'轉int: " + charValue); // 65
    }
}

強制類型轉換(顯式轉換)

當把大範圍類型的數據賦值給小範圍類型的變量時,需要手動進行強制類型轉換。就像大杯子的水倒進小杯子,可能溢出(數據丟失),需要手動操作。

語法:目標類型 變量名 = (目標類型) 源數據;

代碼示例:

複製

public class ForceCastDemo {
    public static void main(String[] args) {
        // int → byte(可能溢出)
        int bigNum = 200;
        byte smallNum = (byte) bigNum; // 強制轉換
        System.out.println("200強制轉為byte: " + smallNum); // -56(溢出,因為byte最大127)

        // double → int(小數部分丟失)
        double d = 3.14;
        int num = (int) d; // 強制轉換,小數部分被截斷
        System.out.println("3.14強制轉為int: " + num); // 3

        // long → int(可能溢出)
        long l = 12345678901L;
        int i = (int) l; // 強制轉換
        System.out.println("12345678901強制轉為int: " + i); // 1942913985(溢出)

        // 演示溢出原因
        System.out.println("byte的最大值: " + Byte.MAX_VALUE); // 127
        System.out.println("byte的最小值: " + Byte.MIN_VALUE); // -128
        // 200超出byte範圍,二進制存儲時發生溢出,結果變為負數
    }
}

⚠️ 強制轉換風險:強制轉換可能導致數據溢出(如200轉byte變成-56)或精度丟失(如3.14轉int變成3),使用時要確保源數據在目標類型範圍內。

常見類型轉換錯誤及解決方法

錯誤1:直接賦值大範圍類型給小範圍類型

複製

// 錯誤示例
int a = 100;
byte b = a; // 編譯錯誤:不兼容的類型: 從int轉換到byte可能會有損失

解決方法:使用強制類型轉換,並確保值在目標類型範圍內:

複製

// 正確示例
int a = 100;
byte b = (byte) a; // 正確,100在byte範圍內(-128~127)
System.out.println(b); // 100

錯誤2:不同類型數據直接運算

複製

// 錯誤示例
int num1 = 10;
double num2 = 3.5;
int result = num1 + num2; // 編譯錯誤:不兼容的類型: 從double轉換到int可能會有損失

解決方法:將結果強制轉換為目標類型,或先將小範圍類型轉換為大範圍類型再運算:

複製

// 正確示例1:強制轉換結果
int num1 = 10;
double num2 = 3.5;
int result1 = (int) (num1 + num2); // 先運算後轉換
System.out.println(result1); // 13

// 正確示例2:提升為大範圍類型運算
double result2 = num1 + num2; // num1自動提升為double,結果為double
System.out.println(result2); // 13.5

錯誤3:字符串與基本類型轉換錯誤

複製

// 錯誤示例
String str = "123";
int num = str; // 編譯錯誤:不兼容的類型: String無法轉換為int

解決方法:使用包裝類的parseXxx()方法:

複製

// 正確示例
String str = "123";
int num = Integer.parseInt(str); // 使用Integer.parseInt()轉換
System.out.println(num + 1); // 124

// 轉換失敗處理(字符串不是數字)
String wrongStr = "abc";
try {
    int wrongNum = Integer.parseInt(wrongStr);
} catch (NumberFormatException e) {
    System.out.println("轉換失敗:字符串不是有效的整數");
}

💡 包裝類:每個基本類型都有對應的包裝類(如int對應Integer,double對應Double),提供了類型轉換等工具方法。字符串轉基本類型使用parseXxx()方法,基本類型轉字符串可以用String.valueOf(值)或直接拼接空字符串。

類型轉換的實用技巧

  1. 避免不必要的轉換:能使用自動轉換就不要用強制轉換
  2. 轉換前檢查範圍:強制轉換前確保值在目標類型範圍內,如:

複製

int a = 200;
   if (a >= Byte.MIN_VALUE && a <= Byte.MAX_VALUE) {
       byte b = (byte) a;
       System.out.println(b);
   } else {
       System.out.println("值超出byte範圍");
   }

  1. 浮點數轉整數使用Math工具類:需要四捨五入時用Math.round(),而不是直接強制轉換:

複製

double d = 3.7;
   int num1 = (int) d; // 3(截斷)
   int num2 = (int) Math.round(d); // 4(四捨五入)

綜合案例:數據類型與運算符實踐

下面我們通過一個綜合案例,鞏固今天學習的所有知識點:

複製

public class ComprehensiveDemo {
    public static void main(String[] args) {
        // 1. 定義各種數據類型的變量
        byte age = 25;
        short heightCm = 175;
        int weightKg = 65;
        long phoneNumber = 13812345678L; // 注意加L
        float bmi = (float) (weightKg / (heightCm / 100.0)); // BMI = 體重(kg)/身高(m)²
        char gender = '男';
        boolean isStudent = true;

        // 2. 使用運算符計算
        int nextYearAge = age + 1;
        double heightM = heightCm / 100.0; // 身高轉米
        double bmiPrecise = weightKg / (heightM * heightM); // 更精確的BMI計算

        // 3. 使用邏輯運算符判斷
        boolean isNormalBmi = (bmiPrecise >= 18.5) && (bmiPrecise <= 23.9);

        // 4. 輸出結果
        System.out.println("=== 個人信息 ===");
        System.out.println("年齡:" + age + "歲,明年:" + nextYearAge + "歲");
        System.out.println("身高:" + heightCm + "cm (" + heightM + "m)");
        System.out.println("體重:" + weightKg + "kg");
        System.out.println("BMI值:" + bmi + " (粗略計算)," + bmiPrecise + " (精確計算)");
        System.out.println("性別:" + gender);
        System.out.println("是否學生:" + isStudent);
        System.out.println("BMI是否正常:" + isNormalBmi);
        System.out.println("電話號碼:" + phoneNumber);

        // 5. 演示類型轉換
        System.out.println("\n=== 類型轉換演示 ===");
        System.out.println("身高(cm)轉米: " + heightCm + "cm = " + heightM + "m");
        System.out.println("BMI精確值轉整數: " + (int) bmiPrecise); // 截斷小數
        System.out.println("BMI四捨五入: " + Math.round(bmiPrecise)); // 四捨五入
    }
}

運行結果:

複製

=== 個人信息 ===
年齡:25歲,明年:26歲
身高:175cm (1.75m)
體重:65kg
BMI值:21.0 (粗略計算),21.224489795918366 (精確計算)
性別:男
是否學生:true
BMI是否正常:true
電話號碼:13812345678

=== 類型轉換演示 ===
身高(cm)轉米: 175cm = 1.75m
BMI精確值轉整數: 21
BMI四捨五入: 21

總結與練習

今日重點總結

  1. 基本數據類型:8種基本類型(4整數、2浮點、char、boolean),重點掌握它們的內存佔用和應用場景
  2. 變量與常量:變量是可變的容器,常量是不可變的值(用final修飾),遵循命名規則
  3. 運算符:算術、賦值、比較、邏輯運算符,注意優先級和短路特性
  4. 類型轉換:自動轉換(小→大)和強制轉換(大→小),強制轉換可能導致溢出或精度丟失

課後練習

  1. 基礎練習:編寫程序,定義不同類型的變量,使用各種運算符進行計算,並打印結果。
  2. BMI計算器:輸入身高(cm)和體重(kg),計算BMI值並判斷體型(偏瘦<18.5,正常18.5-23.9,超重24-27.9,肥胖≥28)。
  3. 類型轉換挑戰:思考以下代碼的輸出結果,並解釋原因:

複製

public class ConversionChallenge {
       public static void main(String[] args) {
           int a = 128;
           byte b = (byte) a;
           System.out.println(b); // 輸出什麼?為什麼?

           char c = '中';
           int d = c;
           System.out.println(d); // 輸出什麼?代表什麼?

           double e = 1.5;
           int f = (int) e;
           int g = (int) Math.round(e);
           System.out.println(f + ", " + g); // 輸出什麼?區別是什麼?
       }
   }

常見問題解答

Q1:為什麼需要多種數據類型?
A1:為了節省內存空間提高效率。存儲年齡用byte(1字節)比long(8字節)更節省空間,處理大整數才需要long類型。

Q2:float和double哪個更好?
A2:大多數情況推薦使用double,因為它精度更高。只有在內存緊張(如大量浮點數據)時才考慮float。

Q3:自增運算符i++和++i有什麼區別?
A3:單獨使用時沒有區別,都使i增加1。在表達式中使用時,i++先使用i的值再自增,++i先自增再使用i的值。

Q4:強制類型轉換時如何避免溢出?
A4:可以使用包裝類的MAX_VALUE和MIN_VALUE檢查範圍,如if (num <= Integer.MAX_VALUE && num >= Integer.MIN_VALUE)。

通過今天的學習,我們已經掌握了Java編程的基礎構建塊。明天我們將學習流程控制語句,讓程序能夠根據條件執行不同代碼,實現更復雜的邏輯!