包裝類

有空發表於2024-11-17

包裝類就是基本資料型別所對應的引用資料型別. 就是把基本資料型別變成了一個物件.

包裝類可以理解為: 用一個物件, 將基本資料型別包起來.

集合不能儲存基本資料型別, 只能儲存物件.

圖片名稱

JDK5 對獲取物件的方式進行了最佳化.

JDK5 之前, 如果要獲取包裝類的物件, 需要根據構造方法自己 new. 或者根據靜態方法 valueOf() 來獲取, 這是一個被過載的方法.

圖片名稱

valueOf() 原始碼:

圖片名稱

傳進來的引數, 如果在 [-128, 127] 範圍內, 就直接從一個陣列中去獲取, 否則 new 一個出來.

進入 1080 行的 cache 的原始碼:

圖片名稱

可以看見, cache 是一個 Integer 型別的陣列.

low 和 high 的值:

圖片名稱

程式示例:

public class IntegerDemo1 {
    public static void main(String[] args) {
        /*
         * public Integer(int value) 根據傳遞的整數建立一個Integer物件
         * public Integer(String s) 根據傳遞的字串建立一個Integer物件
         * public static Integer valueOf(int i) 根據傳遞的整數建立一個Integer物件
         * public static Integer valueof(String s) 根據傳遞的字串建立一個Integer物件
         * public static Integer valueof(String s, int radix) 根據傳遞的字串和進位制建立一個Integer物件
         */

        // 1.利用構造方法獲取Integer的物件(JDK5以前的方式)
        Integer i1 = new Integer(1);
        Integer i2 = new Integer("1");
        System.out.println(i1);  // 1
        System.out.println(i2);  // 1

        // 2.利用靜態方法獲取Integer的物件(JDK5以前的方式)
        Integer i3 = Integer.valueOf(123); // 123
        Integer i4 = Integer.valueOf("123"); // 123
        Integer i5 = Integer.valueOf("123", 8); // 83

        System.out.println(i3);  // 123
        System.out.println(i4);  // 123
        System.out.println(i5);  // 83

        // 3.這兩種方式獲取物件的區別(掌握)
        // 底層原理: 
        // 因為在實際開發中, -128~127之間的資料, 用的比較多. 
        // 如果每次使用都是new物件, 那麼太浪費記憶體了
        // 所以, 提前把這個範圍之內的每一個資料都建立好物件
        // 如果要用到了不會建立新的, 而是返回已經建立好的物件. 
        Integer i6 = Integer.valueOf(127);
        Integer i7 = Integer.valueOf(127);
        System.out.println(i6 == i7);  // true

        Integer i8 = Integer.valueOf(128);
        Integer i9 = Integer.valueOf(128);
        System.out.println(i8 == i9);  // false

        // 因為看到了new關鍵字, 在Java中, 每一次new都是建立了一個新的物件
        // 所以下面的兩個物件都是new出來, 地址值不一樣. 

        Integer i10 = new Integer(127);
        Integer i11 = new Integer(127);
        System.out.println(i10 == i11);  // false

        Integer i12 = new Integer(128);
        Integer i13 = new Integer(128);
        System.out.println(i12 == i13);  // false
    }
}

程式示例:

public class IntegerDemo2 {
    public static void main(String[] args) {
        // 在以前包裝類如何進行計算

        Integer i1 = new Integer(1);
        Integer i2 = new Integer(2);


        // 需求:要把兩個資料進行相加得到結果3
        // 物件之間是不能直接進行計算的. 
        // 步驟:
        // 1.把物件進行拆箱, 變成基本資料型別
        // 2.相加
        // 3.把得到的結果再次進行裝箱(再變回包裝類)


        int result = i1.intValue() + i2.intValue();
        Integer i3 = new Integer(result);
        System.out.println(i3);
    }
}

程式示例:

public class demo3 {
    public static void main(String[] args) {
        // 在JDK5的時候提出了一個機制:自動裝箱和自動拆箱
        // 自動裝箱:把基本資料型別會自動的變成其對應的包裝類
        // 自動拆箱:把包裝類自動的變成其物件的基本資料型別

        // 在底層, 此時還會去自動呼叫靜態方法valueof得到一個Integer物件, 只不過這個動作不需要我們自己去操作了
        // 自動裝箱的動作
        Integer i1 = 10;

        Integer i2 = new Integer(10);
        // 自動拆箱的動作
        int i = i2;

        // 結論: 在JDK5以後, int和Integer可以看做是同一個東西, 因為在內部可以自動轉化. 
    }
}

包裝類 Integer 的成員方法:

圖片名稱

程式示例:

public class demo4 {
    public static void main(String[] args) {
        /*
         * public static string tobinarystring(int i) 得到二進位制
         * public static string tooctalstring(int i) 得到八進位制
         * public static string toHexstring(int i) 得到十六進位制
         * public static int parseInt(string s) 將字串型別的整數轉成int型別的整數
         */

        // 1.把整數轉成二進位制, 十六進位制
        String str1 = Integer.toBinaryString(100);
        System.out.println(str1);  // 1100100

        // 2.把整數轉成八進位制
        String str2 = Integer.toOctalString(100);
        System.out.println(str2);  // 144

        // 3.把整數轉成十六進位制
        String str3 = Integer.toHexString(100);
        System.out.println(str3);  // 64

        // 4.將字串型別的整數轉成int型別的整數
        // 強型別語言:每種資料在java中都有各自的資料型別
        // 在計算的時候, 如果不是同一種資料型別, 是無法直接計算的. 
        int i = Integer.parseInt("123");
        System.out.println(i);
        System.out.println(i + 1);  // 124
        // 細節1:
        // 在型別轉換的時候, 括號中的引數只能是數字不能是其他, 否則程式碼會報錯
        // 細節2:
        // 8種包裝類當中, 除了Character都有對應的parseXxx的方法, 進行型別轉換
        String str = "true";
        boolean b = Boolean.parseBoolean(str);
        System.out.println(b);
    }
}

程式示例:

import java.util.Scanner;

public class demo5 {
    public static void main(String[] args) {
        // 鍵盤錄入
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入一個字串");
        String str = sc.next();
        System.out.println(str);
        // 弊端:
        // 當我們在使用next, nextInt, nextDouble在接收資料的時候, 遇到空格, 回車, 製表符的時候就停止了
        // 鍵盤錄入的是123 123 那麼此時只能接收到空格前面的資料
        // 我想要的是接收一整行資料
        // 約定:
        // 以後我們如果想要鍵盤錄入, 不管什麼型別, 統一使用nextLine
        // 特點:遇到回車才停止
        String line = sc.nextLine();
        System.out.println(line);
        double v = Double.parseDouble(line);
        System.out.println(v);
    }
}

練習題:

第一題:

import java.util.Scanner;

public class A05_IntegerDemo5 {
    public static void main(String[] args) {
        // 鍵盤錄入
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入一個字串");
        /*
         * String str = sc.next();
         * System.out.println(str);
         */
        // 弊端:
        // 當我們在使用next, nextInt, nextDouble在接收資料的時候, 遇到空格, 回車, 製表符的時候就停止了
        // 鍵盤錄入的是123 123 那麼此時只能接收到空格前面的資料
        // 我想要的是接收一整行資料
        // 約定:
        // 以後我們如果想要鍵盤錄入, 不管什麼型別, 統一使用nextLine
        // 特點:遇到回車才停止
        String line = sc.nextLine();
        System.out.println(line);
        double v = Double.parseDouble(line);
        System.out.println(v);
    }
}

第二題:

public class Test2 {
    public static void main(String[] args) {
        /*
         * 自己實現parseInt方法的效果, 將字串形式的資料轉成整數. 要求:
         * 字串中只能是數字不能有其他字元最少一位, 最多10位日不能開頭
         */

        // 1.定義一個字串
        String str = "123";
        // 2.校驗字串
        // 習慣:會先把異常資料進行過濾, 剩下來就是正常的資料. 
        if (!str.matches("[1-9]\\d{0,9}")) {
            // 錯誤的資料
            System.out.println("資料格式有誤");
        } else {
            // 正確的資料
            System.out.println("資料格式正確");
            // 3.定義一個變數表示最終的結果
            int number = 0;
            // 4.遍歷字串得到裡面的每一個字元
            for (int i = 0; i < str.length(); i++) {
                int c = str.charAt(i) - '0';// 把每一位數字放到number當中
                number = number * 10 + c;
            }
            System.out.println(number);
            System.out.println(number + 1);
        }
    }
}

第三題:

public class Test3 {
    public static void main(String[] args) {
        /*
         * 
         * 定義一個方法自己實現toBinaryString方法的效果, 將一個十進位制整數轉成字串表示的二進位制
         * 
         */
    }

    public static String tobinarystring(int number) {// 6
        // 核心邏輯:
        // 不斷的去除以2, 得到餘數, 一直到商為日就結束. 
        // 還需要把餘數倒著拼接起來

        // 定義一個StringBuilder用來拼接餘數
        StringBuilder sb = new StringBuilder();
        // 利用迴圈不斷的除以2獲取餘數
        while (true) {
            if (number == 0) {
                break;
            }
            // 獲取餘數 %
            int remaindar = number % 2;// 倒著拼接
            sb.insert(0, remaindar);
            // 除以2 /
            number = number / 2;
        }
        return sb.toString();
    }
}

第四題:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public class Test4 {
    public static void main(String[] args) throws ParseException {
        // 請使用程式碼實現計算你活了多少天, 用JDK7和JDK8兩種方式完成
        // JDK7
        // 規則:只要對時間進行計算或者判斷, 都需要先獲取當前時間的毫秒值
        // 1.計算出生年月日的毫秒值
        String birthday = "2000年1月1日";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        Date date = sdf.parse(birthday);
        long birthdayTime = date.getTime();
        // 2.獲取當前時間的毫秒值
        long todayTime = System.currentTimeMillis();
        // 3.計算間隔多少天
        long time = todayTime - birthdayTime;
        System.out.println(time / 1000 / 60 / 60 / 24);

        // JDK8
        LocalDate ld1 = LocalDate.of(2000, 1, 1);
        LocalDate ld2 = LocalDate.now();
        long days = ChronoUnit.DAYS.between(ld1, ld2);
        System.out.println(days);
    }
}

第五題:

import java.time.LocalDate;
import java.util.Calendar;

public class Test5 {
    public static void main(String[] args) {
        /*
         * 判斷任意的一個年份是閏年還是平年要求:用JDK7和JDK8兩種方式判斷提示:
         * 二月有29天是閏年一年有366天是閏年
         */

        // jdk7
        // 我們可以把時間設定為2000年3月1日
        Calendar c = Calendar.getInstance();
        c.set(2000, 2, 1);
        // 月份的範圍:0~11
        // 再把日曆往前減一天
        c.add(Calendar.DAY_OF_MONTH, -1);
        // 看當前的時間是28號還是29號?
        int day = c.get(Calendar.DAY_OF_MONTH);
        System.out.println(day);

        // jdk8
        // 月份的範圍:1~12
        // 設定時間為2000年的3月1日
        LocalDate ld = LocalDate.of(2001, 3, 1);
        // 把時間往前減一天
        LocalDate ld2 = ld.minusDays(1);
        // 獲取這一天是一個月中的幾號
        int day2 = ld2.getDayOfMonth();
        System.out.println(day2);

        // true:閏年
        // false:平年
        System.out.println(ld.isLeapYear());
    }
}

相關文章