一、基本类型包装类
1.1 概念引入
Java 是面向对象的编程语言,但 8 种基本数据类型(byte、short、int、long、float、double、char、boolean)并不属于对象体系。为了让基本类型具备对象特性(如可存储在集合中、可调用方法),Java 提供了对应的包装类,将基本类型 "包装" 成对象。
1.2 包装类对应关系
| 基本类型 | 包装类 | 核心用途 |
|---|---|---|
byte |
Byte |
字节型数据封装 |
short |
Short |
短整型数据封装 |
int |
Integer |
整型数据封装(最常用) |
long |
Long |
长整型数据封装 |
float |
Float |
单精度浮点型数据封装 |
double |
Double |
双精度浮点型数据封装 |
char |
Character |
字符型数据封装 |
boolean |
Boolean |
布尔型数据封装 |
1.3 包装类的特性
- 包装类是不可变类:对象创建后,其内部值无法修改。
- 提供了常量(如
Integer.MAX_VALUE、Double.NaN)和工具方法(如类型转换、进制转换)。 - 包装类是
final修饰的类,不能被继承; - 内部封装了对应的基本类型值,提供了属性和方法操作该值;
- 支持基本类型与对象之间的转换(装箱 / 拆箱)。
二、装箱与拆箱
2.1 手动装箱(基本类型→包装类)
通过包装类的构造方法或valueOf()方法,将基本类型转换为包装类对象。
java
public class BoxDemo {
public static void main(String[] args) {
// 1. 构造方法装箱(JDK9后已标记过时,推荐valueOf)
Integer num1 = new Integer(10);
Character ch1 = new Character('a');
// 2. valueOf()方法装箱(推荐,有缓存优化)
Integer num2 = Integer.valueOf(20);
Double num3 = Double.valueOf(3.14);
System.out.println("手动装箱结果:" + num1 + ", " + num2);
}
}
2.2 手动拆箱(包装类→基本类型)
通过包装类的xxxValue()方法(如intValue()、doubleValue()),将包装类对象转换为基本类型。
java
public class UnboxDemo {
public static void main(String[] args) {
Integer numObj = Integer.valueOf(100);
Double doubleObj = Double.valueOf(2.5);
// 拆箱为基本类型
int num = numObj.intValue();
double d = doubleObj.doubleValue();
System.out.println("拆箱后基本类型:" + num + ", " + d);
}
}
2.3 自动装箱与自动拆箱(JDK5 + 特性)
Java 编译器自动完成装箱 / 拆箱操作,无需手动调用方法,简化代码。
java
public class AutoBoxUnboxDemo {
public static void main(String[] args) {
// 自动装箱:基本类型→包装类
Integer num1 = 10; // 等价于 Integer num1 = Integer.valueOf(10);
Boolean flag = true;// 等价于 Boolean flag = Boolean.valueOf(true);
// 自动拆箱:包装类→基本类型
int num2 = num1; // 等价于 int num2 = num1.intValue();
boolean b = flag; // 等价于 boolean b = flag.booleanValue();
// 运算时自动拆箱
Integer sum = num1 + 20; // num1先拆箱为int,计算后再装箱为Integer
System.out.println("自动装箱拆箱运算:" + sum);
}
}
注意点:
-
包装类对象可能为
null,自动拆箱时若对象为null会抛出NullPointerException:javaInteger nullObj = null; int n = nullObj; // 运行时抛出NullPointerException -
Integer的valueOf()有缓存机制(-128~127),超出范围会创建新对象:javaInteger a = 127; Integer b = 127; System.out.println(a == b); // true(缓存) Integer c = 128; Integer d = 128; System.out.println(c == d); // false(新对象)
三、基本类型与字符串转换
3.1 基本类型→字符串
方法 1:拼接空字符串(简单但效率较低)
java
int num = 100;
String str1 = num + "";
方法 2:String.valueOf()(推荐,无空指针风险)
java
double d = 3.14;
String str2 = String.valueOf(d);
方法 3:包装类的toString()方法
java
boolean flag = true;
String str3 = Boolean.toString(flag);
3.2 字符串→基本类型
方法 1:包装类的parseXxx()方法(常用)
java
String strNum = "123";
int num = Integer.parseInt(strNum);
double d = Double.parseDouble("3.14");
boolean flag = Boolean.parseBoolean("true");
方法 2:包装类的valueOf()方法(返回包装类,可自动拆箱)
java
String strLong = "1000000";
long l = Long.valueOf(strLong); // 自动拆箱为long
注意:
字符串格式不正确会抛出NumberFormatException:
java
String errStr = "abc";
int errNum = Integer.parseInt(errStr); // 抛出NumberFormatException
四、字符串 String 类
4.1 String 类特性
- 不可变性:String 对象创建后,其字符序列(底层 char 数组)不可修改,任何修改操作都会生成新的 String 对象。
- 常量池优化 :字符串字面量(如
"abc")会存储在字符串常量池中,相同字面量复用对象,节省内存。
4.2 String 对象创建方式
java
public class StringCreateDemo {
public static void main(String[] args) {
// 方式1:字面量创建(存储在常量池)
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // true(常量池复用对象)
// 方式2:new关键字创建(堆内存新对象)
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s3 == s4); // false(不同对象)
System.out.println(s3.equals(s4)); // true(内容相同)
// 方式3:拼接创建(编译期优化)
String s5 = "He" + "llo"; // 编译期优化为"Hello",指向常量池
System.out.println(s1 == s5); // true
// 变量拼接(运行期创建新对象)
String a = "He";
String s6 = a + "llo";
System.out.println(s1 == s6); // false
}
}
五、String 常用方法
5.1 获取相关方法
java
public class StringMethodDemo1 {
public static void main(String[] args) {
String str = "Java进阶笔记";
// 1. length():获取字符串长度
int len = str.length();
System.out.println("长度:" + len); // 输出7
// 2. charAt(int index):获取指定索引的字符
char ch = str.charAt(2);
System.out.println("索引2的字符:" + ch); // 输出v
// 3. indexOf(String str):查找子串首次出现的索引,无则返回-1
int index = str.indexOf("进阶");
System.out.println("进阶首次出现索引:" + index); // 输出4
// 4. lastIndexOf(String str):查找子串最后出现的索引
String str2 = "ababa";
int lastIndex = str2.lastIndexOf("aba");
System.out.println("aba最后出现索引:" + lastIndex); // 输出2
}
}
5.2 判断相关方法
java
public class StringMethodDemo2 {
public static void main(String[] args) {
String str = "HelloWorld";
// 1. equals(Object obj):比较内容是否相同(区分大小写)
boolean eq = str.equals("helloworld");
System.out.println("equals比较:" + eq); // false
// 2. equalsIgnoreCase(String str):忽略大小写比较
boolean eqIgnoreCase = str.equalsIgnoreCase("helloworld");
System.out.println("忽略大小写比较:" + eqIgnoreCase); // true
// 3. contains(CharSequence s):是否包含指定子串
boolean contains = str.contains("World");
System.out.println("是否包含World:" + contains); // true
// 4. startsWith(String prefix):是否以指定前缀开头
boolean start = str.startsWith("Hello");
System.out.println("是否以Hello开头:" + start); // true
// 5. endsWith(String suffix):是否以指定后缀结尾
boolean end = str.endsWith("d");
System.out.println("是否以d结尾:" + end); // true
// 6. isEmpty():是否为空字符串(长度为0)
boolean empty = "".isEmpty();
System.out.println("空字符串判断:" + empty); // true
}
}
5.3 转换相关方法
java
public class StringMethodDemo3 {
public static void main(String[] args) {
String str = " Java String ";
// 1. toUpperCase():转大写
String upper = str.toUpperCase();
System.out.println("转大写:" + upper); // 输出" JAVA STRING "
// 2. toLowerCase():转小写
String lower = str.toLowerCase();
System.out.println("转小写:" + lower); // 输出" java string "
// 3. trim():去除首尾空格(JDK11+可用strip(),支持Unicode空白字符)
String trimStr = str.trim();
System.out.println("去除首尾空格:[" + trimStr + "]"); // 输出"[Java String]"
// 4. toCharArray():转为字符数组
char[] chars = "abc".toCharArray();
System.out.println("字符数组:" + chars[1]); // 输出b
// 5. replace(CharSequence target, CharSequence replacement):替换子串
String replaceStr = "abac".replace("a", "x");
System.out.println("替换结果:" + replaceStr); // 输出xbxc
}
}
5.4 截取与分割方法
java
public class StringMethodDemo4 {
public static void main(String[] args) {
String str = "Java-进阶-2025-笔记";
// 1. substring(int beginIndex):从指定索引截取到末尾
String sub1 = str.substring(5);
System.out.println("截取结果1:" + sub1); // 输出"进阶-2025-笔记"
// 2. substring(int beginIndex, int endIndex):截取[begin,end)区间
String sub2 = str.substring(5, 7);
System.out.println("截取结果2:" + sub2); // 输出"进阶"
// 3. split(String regex):按正则分割字符串
String[] arr = str.split("-");
for (String s : arr) {
System.out.print(s + " "); // 输出Java 进阶 2025 笔记
}
}
}
六、equals 方法详解
6.1 equals 与 == 的区别
==:- 比较基本类型:判断值是否相等。
- 比较引用类型:判断对象地址是否相同(是否为同一个对象)。
equals():- Object 类中默认实现是
==(比较地址)。 - String 类重写了
equals(),改为比较字符序列内容。
- Object 类中默认实现是
6.2 String 类 equals 源码解析
java
public boolean equals(Object anObject) {
if (this == anObject) { // 先判断地址,相同则直接返回true
return true;
}
if (anObject instanceof String) { // 判断是否为String类型
String anotherString = (String)anObject;
int n = value.length; // value是String底层存储字符的char数组
if (n == anotherString.value.length) { // 长度相同才继续比较
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) { // 逐字符比较
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
6.3 自定义类重写 equals
若自定义类需要按内容比较,需重写equals():
java
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 重写equals,按name和age比较
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
}
public class EqualsDemo {
public static void main(String[] args) {
Student s1 = new Student("张三", 20);
Student s2 = new Student("张三", 20);
System.out.println(s1 == s2); // false(不同对象)
System.out.println(s1.equals(s2)); // true(内容相同)
}
}
七、toString 方法
7.1 toString 作用
返回对象的字符串表示,默认输出 "类名 @哈希码",重写后可输出对象的属性信息,方便调试。
7.2 默认实现与重写
java
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写toString方法
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class ToStringDemo {
public static void main(String[] args) {
Person p = new Person("李四", 25);
// 默认toString(未重写):Person@1b6d3586
// 重写后:Person{name='李四', age=25}
System.out.println(p); // 等价于System.out.println(p.toString());
}
}
八、可变字符串(StringBuilder & StringBuffer)
8.1 为什么需要可变字符串
String 是不可变的,频繁拼接会创建大量临时对象,效率低下。可变字符串类(StringBuilder/StringBuffer)支持直接修改字符序列,性能更高。
8.2 StringBuilder 与 StringBuffer 区别
| 特性 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | 不安全(效率高) | 安全(效率低) |
| 适用场景 | 单线程环境 | 多线程环境 |
| 性能 | 快 | 较慢 |
8.3 常用方法
java
public class StringBuilderDemo {
public static void main(String[] args) {
// 创建StringBuilder对象
StringBuilder sb = new StringBuilder("Java");
// 1. append(...):追加内容
sb.append("进阶");
sb.append(2025);
System.out.println("append后:" + sb); // 输出Java进阶2025
// 2. insert(int offset, ...):插入内容
sb.insert(4, "-");
System.out.println("insert后:" + sb); // 输出Java-进阶2025
// 3. replace(int start, int end, String str):替换
sb.replace(5, 7, "高级");
System.out.println("replace后:" + sb); // 输出Java-高级2025
// 4. delete(int start, int end):删除
sb.delete(8, 12);
System.out.println("delete后:" + sb); // 输出Java-高级
// 5. reverse():反转
sb.reverse();
System.out.println("reverse后:" + sb); // 输出级高-avaJ
// 6. 转为String
String result = sb.toString();
System.out.println("最终String:" + result);
}
}
8.4 性能对比(String vs StringBuilder)
java
public class PerformanceDemo {
public static void main(String[] args) {
// String拼接(低效)
long start1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 10000; i++) {
s += i;
}
long end1 = System.currentTimeMillis();
System.out.println("String拼接耗时:" + (end1 - start1) + "ms");
// StringBuilder拼接(高效)
long start2 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
long end2 = System.currentTimeMillis();
System.out.println("StringBuilder拼接耗时:" + (end2 - start2) + "ms");
}
}
输出示例:
String拼接耗时:150ms
StringBuilder拼接耗时:1ms
总结
掌握这些知识点,能有效解决开发中的字符串处理、类型转换等高频问题,同时规避常见坑点
-
本文覆盖了 Java 进阶中包装类、字符串操作的核心知识点:
-
包装类实现基本类型的对象化,自动装箱拆箱简化代码但需注意缓存池和空指针问题;
-
基本类型与字符串转换有固定套路,推荐使用
String.valueOf()和包装类.parseXxx(); -
String 类不可变,核心方法和
equals()、toString()是面试重点; -
可变字符串优先使用
StringBuilder(单线程),多线程用StringBuffer。