包装类
包装类就是基本数据类型所对应的引用数据类型. 就是把基本数据类型变成了一个对象.
包装类可以理解为: 用一个对象, 将基本数据类型包起来.

图 1
Java 中万物皆对象, 所有的东西都可以看作是一个对象, 而且由于多态特性, 所有的对象都可以用 Object 来表示.

图 2

图 3
此时, 如果没有包装类, 传递过来了一个整数, 方法就无法接受, 程序就有局限性. 另一方面, 集合不能存储基本数据类型, 只能存储对象.
JDK5 对获取对象的方式进行了优化.
JDK5 之前, 如果要获取包装类的对象, 需要根据构造方法自己 new. 或者根据静态方法 valueOf() 来获取, 这是一个被重载的方法.

图 4
valueOf()
源码:

图 5
传进来的参数, 如果在 [-128, 127] 范围内, 就直接从一个数组中去获取, 否则 new 一个出来.
进入 1080 行的 cache 的源码:

图 6
可以看见, cache 是一个 Integer 类型的数组.
low 和 high 的值:

图 7
程序示例:
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 可以看做是同一个东西, 因为在内部可以自动转化. } }

图 8
包装类 Integer 的成员方法:

图 9
程序示例:
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 Demo { 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); System.out.println(line + 1); double v = Double.parseDouble(line); System.out.println(v); System.out.println(v + 1); } }
执行结果:
请输入一个字符串 2.3 2.3 2.31 2.3 3.3
练习题:
第一题:
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 位, 0 不能开头 */ // 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, 得到余数, 一直到商为日就结束. // 还需要把余数倒着拼接起来 // 定义一个 StringBuilde r用来拼接余数 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()); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术