当前位置: 首页 > news >正文

4.2java包装类

Java中的基本数据类型不具备对象特性,为了使其能够参与面向对象操作,Java提供了对应的包装类,如IntegerDouble等。包装类属于引用类型,继承自Object类,具备对象特性,可用于泛型、类型转换等场景。Java 5引入了自动装箱和自动拆箱机制,简化了基本数据类型与包装类之间的转换。自动装箱通过valueOf()方法实现,自动拆箱通过xxxValue()方法实现。使用包装类时需注意缓存问题和空指针异常。此外,Java提供了StringBuilderStringBufferStringJoiner等类,用于高效处理字符串拼接操作。StringBuilder适用于单线程环境,StringBuffer适用于多线程环境,StringJoiner则用于将多个字符串用指定分隔符连接。这些工具类在处理批量字符串拼接时,能有效提升性能并减少内存开销。

 在 Java 里,基本数据类型不具备对象的特性,像不能调用方法、参与面向对象的操作等。为了让基本数据类型也能有对象的行为,Java 提供了对应的包装类。同时,自动拆箱和自动装箱机制让基本数据类型和包装类之间的转换更加便捷。

包装类概述

Java 为 8 种基本数据类型都提供了对应的包装类,具体如下:

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

包装类属于引用类型,继承自 Object 类,具备对象的特性,能调用方法和参与面向对象的操作。

包装类的用途

  • 作为泛型的类型参数:泛型只能使用引用类型,不能使用基本数据类型,这时就需要用到包装类。例如:
import java.util.ArrayList;
import java.util.List;public class WrapperClassGenericExample {public static void main(String[] args) {// 正确,使用包装类作为泛型类型参数List<Integer> intList = new ArrayList<>();intList.add(1);// 错误,不能使用基本数据类型作为泛型类型参数// List<int> wrongList = new ArrayList<>(); }
}

  • 包含实用方法:包装类提供了一些实用的方法,像类型转换、进制转换等。例如:
public class WrapperClassMethodExample {public static void main(String[] args) {String str = "123";// 将字符串转换为整数int num = Integer.parseInt(str); System.out.println(num);int decimal = 255;// 将十进制数转换为十六进制字符串String hex = Integer.toHexString(decimal); System.out.println(hex);}
}

自动装箱和自动拆箱

自动装箱

自动装箱指的是把基本数据类型自动转换为对应的包装类对象。在 Java 5 之后引入了自动装箱机制,让代码更简洁。例如:

public class AutoBoxingExample {public static void main(String[] args) {int num = 10;// 自动装箱,将 int 类型的 num 转换为 Integer 类型的 objInteger obj = num; System.out.println(obj);}
}
自动拆箱

自动拆箱是把包装类对象自动转换为对应的基本数据类型。例如:

public class AutoUnboxingExample {public static void main(String[] args) {Integer obj = 20;// 自动拆箱,将 Integer 类型的 obj 转换为 int 类型的 numint num = obj; System.out.println(num);}
}
自动装箱和拆箱的实现原理

自动装箱和拆箱是通过编译器在编译阶段自动插入相应的方法调用实现的。具体来说,自动装箱调用的是包装类的 valueOf() 方法,自动拆箱调用的是包装类的 xxxValue() 方法(xxx 代表基本数据类型)。例如:

public class AutoBoxingUnboxingPrinciple {public static void main(String[] args) {// 自动装箱,实际调用 Integer.valueOf(30)Integer obj = 30; // 自动拆箱,实际调用 obj.intValue()int num = obj; }
}
注意事项
  • 缓存问题:部分包装类(如 IntegerByteShortLongCharacter)会对一定范围内的值进行缓存,以提高性能。例如,Integer 类会缓存 -128 到 127 之间的值,当使用自动装箱创建这个范围内的 Integer 对象时,会直接从缓存中获取,而不是创建新对象。示例如下:
public class WrapperClassCacheExample {public static void main(String[] args) {Integer a = 100;Integer b = 100;// 输出 true,因为 100 在缓存范围内,a 和 b 引用同一个对象System.out.println(a == b); Integer c = 200;Integer d = 200;// 输出 false,因为 200 不在缓存范围内,c 和 d 是不同的对象System.out.println(c == d); }
}

  • 空指针异常:在进行自动拆箱时,如果包装类对象为 null,会抛出 NullPointerException 异常。例如:
public class NullPointerInAutoUnboxing {public static void main(String[] args) {Integer obj = null;// 会抛出 NullPointerException 异常int num = obj; }
}

通过使用包装类、自动装箱和自动拆箱机制,Java 让基本数据类型和对象之间的交互更加灵活和方便。不过在使用过程中,要注意缓存问题和空指针异常等潜在风险

批量字符串拼接操作

在 Java 里,String 类是不可变的,这意味着一旦创建了一个 String 对象,它的内容就不能被改变。当使用 + 运算符进行字符串拼接时,每次拼接操作都会创建一个新的 String 对象。如果进行批量拼接,会产生大量临时对象,这不仅会占用额外的内存空间,还会增加垃圾回收的负担,从而影响性能。

1. StringBuilder

StringBuilder 是一个可变的字符序列,它提供了高效的字符串拼接操作。在 JDK 1.5 中引入,是非线程安全的,因此在单线程环境下性能较高。

常用方法
  • append():用于在当前字符序列末尾追加各种类型的数据。
  • insert():在指定位置插入各种类型的数据。
  • delete():删除指定位置的字符。
  • reverse():反转当前字符序列。
示例代码
public class StringBuilderExample {public static void main(String[] args) {StringBuilder sb = new StringBuilder();// 追加字符串sb.append("Hello");sb.append(" ");sb.append("World");// 在指定位置插入字符串sb.insert(5, ",");// 删除指定位置的字符sb.delete(5, 6);// 反转字符串sb.reverse();System.out.println(sb.toString()); // 输出 dlroW olleH}
}
适用场景

适用于单线程环境下需要频繁进行字符串拼接、修改等操作的场景,例如在循环中动态构建字符串。

2. StringBuffer

StringBuffer 也是一个可变的字符序列,与 StringBuilder 类似。它是线程安全的,因为它的大部分方法都被 synchronized 关键字修饰,因此在多线程环境下可以保证数据的一致性,但性能相对较低。

常用方法

StringBuffer 的方法与 StringBuilder 基本相同,如 append()insert()delete()reverse() 等。

示例代码
public class StringBufferExample {public static void main(String[] args) {StringBuffer sb = new StringBuffer();sb.append("Hello");sb.append(" ");sb.append("Java");System.out.println(sb.toString()); // 输出 Hello Java}
}
适用场景

适用于多线程环境下需要频繁进行字符串拼接、修改等操作,且需要保证线程安全的场景。

3. StringJoiner

StringJoiner 是 Java 8 引入的一个类,用于方便地将多个字符串用指定的分隔符连接起来,还可以指定前缀和后缀。

常用方法
  • add():添加一个元素到 StringJoiner 中。
  • merge():合并另一个 StringJoiner 的内容。
  • setEmptyValue():设置当没有元素时的空值表示。
示例代码
import java.util.StringJoiner;public class StringJoinerExample {public static void main(String[] args) {// 指定分隔符、前缀和后缀StringJoiner sj = new StringJoiner(", ", "[", "]");sj.add("Apple");sj.add("Banana");sj.add("Cherry");System.out.println(sj.toString()); // 输出 [Apple, Banana, Cherry]// 合并另一个 StringJoinerStringJoiner anotherSj = new StringJoiner("; ");anotherSj.add("Dog");anotherSj.add("Cat");sj.merge(anotherSj);System.out.println(sj.toString()); // 输出 [Apple, Banana, Cherry, Dog; Cat]}
}

适用场景

适用于需要将多个字符串用特定分隔符连接起来的场景,例如将数组元素连接成一个字符串。

性能对比

package com.example.pkg4;import java.util.StringJoiner;public class Test3 {public static void main(String[] args) {int n = 10000;// 使用 + 运算符进行字符串拼接long startTime1 = System.currentTimeMillis();String result1 = "";for (int i = 0; i < n; i++) {result1 = result1 + Integer.toString(i);}long endTime1 = System.currentTimeMillis();System.out.println("使用 + 运算符拼接耗时: " + (endTime1 - startTime1) + " 毫秒");// 使用 StringBuilder 进行字符串拼接long startTime2 = System.currentTimeMillis();StringBuilder sb = new StringBuilder();for (int i = 0; i < n; i++) {sb.append(Integer.toString(i));}String result2 = sb.toString();long endTime2 = System.currentTimeMillis();System.out.println("使用 StringBuilder 拼接耗时: " + (endTime2 - startTime2) + " 毫秒");// 使用 StringBuffer 进行字符串拼接long startTime3 = System.currentTimeMillis();StringBuffer strbuf = new StringBuffer();for (int i = 0; i < n; i++) {strbuf.append(Integer.toString(i));}String result3 = strbuf.toString();long endTime3 = System.currentTimeMillis();System.out.println("使用 StringBuffer 拼接耗时: " + (endTime3 - startTime3) + " 毫秒");// 使用 StringJoiner 进行字符串拼接long startTime4 = System.currentTimeMillis();StringJoiner strjoin = new StringJoiner("");for (int i = 0; i < n; i++) {strjoin.add(Integer.toString(i));}String result4 = strjoin.toString();long endTime4 = System.currentTimeMillis();System.out.println("使用 StringJoiner 拼接耗时: " + (endTime4 - startTime4) + " 毫秒");}}

总结

  • StringBuilder:单线程环境下,性能高,用于频繁的字符串操作。
  • StringBuffer:多线程环境下,线程安全,用于频繁的字符串操作。
  • StringJoiner:用于方便地将多个字符串用指定分隔符连接起来,可指定前缀和后缀。

相关文章:

  • STM32--PWM--函数
  • 微软系统 红帽系统 网络故障排查:ping、traceroute、netstat
  • 40-算法打卡-二叉树-深度优先(前、中、后序遍历)-递归遍历-第四十天
  • 蓝绿激光对潜通信介绍
  • 《微机原理》微机程序段 计算机编程数据分区
  • 量化交易策略的运行
  • 【赛元8523触摸按键开发调试】
  • 【某OTA网站】phantom-token 1004
  • 基于 Ubuntu 24.04 部署 WebDAV
  • 【PHP】基于币安链,一个完整的USDT转账示例
  • C语言实现小波变换去噪
  • Go语言的逃逸分析是怎么进行的
  • docker 镜像的导出和导入(导出完整镜像和导出容器快照)
  • Docker存储空间不足与迁移实战:从根目录爆满到高效扩容
  • 在线服务器具体是指什么?
  • 垃圾分类宣教小程序源码介绍
  • Android Framework 记录之一
  • WDG看门狗(独立看门狗和窗口看门狗)
  • 解决SQL Server SQL语句性能问题(9)——正确使用索引
  • 申能集团笔试1
  • 巴总理召开国家指挥当局紧急会议
  • 要更加冷静地看待“东升西降”的判断
  • 花2万多在海底捞办婚礼,连锁餐企要抢酒楼的婚宴生意?
  • 工程院院士葛世荣获聘任为江西理工大学校长
  • 总奖池超百万!第五届七猫现实题材征文大赛颁奖在即
  • 巴基斯坦称约50名印度士兵在克什米尔实控线丧生