包裝類就是基本資料型別所對應的引用資料型別. 就是把基本資料型別變成了一個物件.
包裝類可以理解為: 用一個物件, 將基本資料型別包起來.
集合不能儲存基本資料型別, 只能儲存物件.
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());
}
}