Java 常用类详解
Java 中的常用类,涵盖八大包装类(Boolean、Character 等)及自动装箱拆箱机制。详细对比了 String、StringBuffer 和 StringBuilder 的特性、内存布局及使用场景。此外还讲解了 Math、Arrays、System 工具类的常用方法,以及 BigInteger 和 BigDecimal 在大数据处理中的应用,最后介绍了 JDK 8 引入的日期时间 API(LocalDate、LocalDateTime 等)及其格式化方式。

Java 中的常用类,涵盖八大包装类(Boolean、Character 等)及自动装箱拆箱机制。详细对比了 String、StringBuffer 和 StringBuilder 的特性、内存布局及使用场景。此外还讲解了 Math、Arrays、System 工具类的常用方法,以及 BigInteger 和 BigDecimal 在大数据处理中的应用,最后介绍了 JDK 8 引入的日期时间 API(LocalDate、LocalDateTime 等)及其格式化方式。

八种基本数据类型相应的引用类型——包装类
boolean--Boolean char--Character byte--Byte short--Short int--Integer long--Long float--Float double--Double



编译器底层优化:实现自动装箱和拆箱
public class Wrapper {
public static void main(String[] args) {
// jdk 5 前的 手动装箱和手动拆箱
// 装箱:基本类型-->包装类型
// 拆箱:包装类型-->基本类型
// 1.1 手动装箱
int i = 1;
// 第一种方式
Integer integer1 = Integer.valueOf(i);
// 第二种方式
Integer integer2 = new Integer(i);
// 1.2 手动拆箱
int j = integer1.intValue();
// 2.1 自动装箱
int m = 10;
Integer integer3 = m;
// 底层调用:Integer.valueOf(m),属于编译器的底层优化
// 2.2 自动拆箱
Integer integer4 = new Integer(99);
int n = integer4;
// 底层调用:integer4.intValue(),属于编译器的底层优化
}
}
public class CommenMethod {
public static void main(String[] args) {
// 将 wrapper 转换为 String
int i = 100;
// 1.String str = i + "";
// 2.String str1 = Integer.toString(i);
// 3.String str2 = String.valueOf(i);
System.out.println(i);
System.out.println(str1);
System.out.println(str2);
// 将 String 转换为 wrapper
String str3 = "1234";
int j = Integer.parseInt(str3);
int m = new Integer(str3); // 利用 Integer 的重载构造器
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
char c = 'a';
System.out.println(Character.isDigit(c));
System.out.println(Character.isLetter(c));
System.out.println(Character.isUpperCase(c));
System.out.println(Character.isLowerCase(c));
System.out.println(Character.toUpperCase(c));
System.out.println(Character.toLowerCase(c));
System.out.println(Character.isWhitespace(c));
}
}

数字常量直接赋值给 Integer 类对象:主要看范围:-128 到 127 就是直接赋值(基本数据类型)
若不是则 new 创建 Integer 对象(引用数据类型)

注:只要有基本数据类型,就会判断值是否相等,因为包装类会进行自动拆箱!!!

两种方式:
1. 直接赋值:String s = "lcz"
2. 调用构造器:String s1 = new String("lcz")
解读:
1. 先从常量池查看是否有"lcz"数据空间,若有,直接指向;若无则重新创建,然后指向。s 最终指向的是常量池的空间地址
2. 先在堆中创建空间,里面维护了 value 属性,指向常量池的"lcz"空间。若无,则重新创建,若有,则通过 value 指向。s1 最终指向的是堆中的空间地址


1):String 类是一个 final 类,不可继承修改 value 值,所以代表不可变的字符序列
2):字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的:因为 value 属性是私有的 final 类型

String a = "hello" + "abc"; // 优化等价 String a = "helloabc"
分析:编译器底层优化,判断创建的常量池对象,是否有引用指向,无则不创建

规则:
String c1 = "ab" + "cd"; // 常量相加,是在池中
String c1 = a + b; // 只要有变量相加,是在堆中
解读:(String c1 = a + b)
1. 先创建一个 StringBuilder sb = new StringBuilder();
2. 执行 sb.append("hello")
3. sb.append("abc")
4. String c = sb.toString()
toString 方法返回的是一个 new 的 value 值是 helloabc 的堆中 String 对象
所以 c 指向 堆中的对象 (String) value[] -> 常量池中 "helloabc"

考察:
堆中对象、栈的创建、常量池的引用
形参指向的改变对实参的指向无影响,但形参对实参指向的对象进行改变会对实参产生影响
public class String01 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = " abc ";
System.out.println(s1.equals(s2));
System.out.println(s1.length());
System.out.println(s1.concat(s2));
System.out.println(s1.indexOf("e"));
System.out.println(s1.lastIndexOf("l"));
System.out.println(s1.substring(1, 3));
System.out.println(s1.substring(1));
System.out.println(s2.trim());
System.out.println(s2.charAt(0));
System.out.println(s2.toLowerCase());
System.out.println(s2.toLowerCase());
System.out.println(s2.charAt(4));
System.out.println(s1.compareTo(s2));
System.out.println(s1.toCharArray());
char[] char1 = s1.toCharArray();
System.out.println(char1[0]);
}
}
StringBuffer 代表可变的字符序列
因为 StringBuffer 字符内容 是存在 char[] value,所以在变化 (增加/删除) 时,不用每次都创建新对象,所以效率高于 String
只有数组空间已满,扩容时需创建新对象,更换地址
1. String 保存的是 字符串常量,里面的值不能更改,每次 String 类的更新实际上就是更改地址,效率较低
// private final char value[] 存放在常量池
2. StringBuffer 保存的是 字符串变量,里面的值可以更改,每次 StringBuffer 的更新实际上可以更新内容,不用每次都更新地址,效率较高
// char[] value 存放在堆
1. StringBuffer(): 初始容量为 16 个字符
2. StringBuffer(int capacity): //capacity[容量] 具有指定初始容量
3. StringBuffer(String str): str.length()+16
1. String——>StringBuffer:
String s = "hello";
(1): StringBuffer b1 = new StringBuffer(s);
(2): StringBuffer b2 = new StringBuffer(); b2.append(s);
2. StringBuffer——>String:
(1): String s1 = b1.toString();
(2): String s2 = new String(b1);
增 append(str) 删 delete(start,end) 改 replace(start,end,str) 查 indexOf(str) 插 insert(index,str) 获取长度 length
public class StringBuffer01 {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("hello");
// 增
s.append(',');
s.append("张三丰").append(100).append(true);
System.out.println(s);
// 删
s.delete(3, 5);
System.out.println(s);
// 改
s.replace(3, 5, "lcz");
System.out.println(s);
// 查
int indexOf = s.indexOf("lcz");
System.out.println(indexOf);
// 插
s.insert(3, "lhc");
System.out.println(s);
// 长度
System.out.println(s.length());
}
}
和 StringBuffer 的区别:StringBuilder 存在线程安全问题
因为没有做互斥处理,没有用 Synchronized 关键字
所以单线程场景用 StringBuilder,多线程场景用 StringBuffer
结论:
1. 如果字符串存在大量的修改操作,一般使用 StringBuffer 或 StringBuilder
2. 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder
3. 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
4. 如果字符串很少修改,被多个对象引用,使用 String,比如配置信息等
public class Test {
public static void main(String[] args) {
String text = "";
long startTime = 0L;
long endTime = 0L;
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
// StringBuffer
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer 的执行时间为:" + (endTime - startTime));
// StringBuilder
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder 的执行时间为:" + (endTime - startTime));
// String
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text += i;
}
endTime = System.currentTimeMillis();
System.out.println("String 的执行时间为:" + (endTime - startTime));
}
}
public class Math01 {
public static void main(String[] args) {
// 1. abs
System.out.println(Math.abs(-9));
// 2. pow, 返回 double
System.out.println(Math.pow(2, 3));
// 3. ceil, 返回 double
System.out.println(Math.ceil(3.5));
// 4. floor, 返回 double
System.out.println(Math.floor(-4.3));
// 5. round, 返回 long
long round = Math.round(4.0001);
System.out.println(round);
// 6. sqrt, 返回 double
double res = Math.sqrt(16);
System.out.println(res);
// 7. random, 返回 [0,1) 之间的小数,返回 double
int a = 2, b = 7;
int num = (int)(a + Math.random()*(b-a+1));
System.out.println(num);
}
}
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class Arrays01 {
public static void main(String[] args) {
// 1. toString(arr)
System.out.println("=== 定制排序前 ===");
Integer[] n1 = {1, 2, 3, 8, 4, 9, 5};
System.out.println(Arrays.toString(n1));
// 2. sort(arr)、sort(arr,new Comparator{})
// Arrays.sort(n1);
// System.out.println("=== 自然排序后 ===");
// System.out.println(Arrays.toString(n1));
System.out.println("=== n1 定制排序后 ===");
Arrays.sort(n1, new Comparator<Integer>() {
// n1 需要为对象数组,不能是基本类型数组
@Override
public int compare(Object o1, Object o2) {
int n1 = (Integer) o1;
int n2 = (Integer) o2;
return n2 - n1;
}
});
System.out.println(Arrays.toString(n1));
// 3. 基于冒泡的定制排序
int[] n2 = {2, 5, 3, 6, 4, 7, 2};
System.out.println("=== n2 定制排序前 ===");
System.out.println(Arrays.toString(n2));
bubbleSort(n2, new Comparator<Integer>() {
@Override
public int compare(Object o1, Object o2) {
int n1 = (Integer) o1;
int n2 = (Integer) o2;
return n2 - n1;
}
});
System.out.println("=== n2 定制排序后");
System.out.println(Arrays.toString(n2));
// 4. binarySearch
// 要求为有序数组,无序数组排为有序也不行,若找不到,返回-(low+1),low 为若存在的索引值
int[] n3 = {1, 2, 3, 4};
System.out.println(Arrays.binarySearch(n3, 2));
// 5. copyOf(arr,len)
// (1):len > arr.length:补 0
// (2):len < 0 抛出异常 NegativeArraySizeException
// (3):底层调用的是 System.arraycopy()
int[] arr2 = Arrays.copyOf(n3, 3);
System.out.println(Arrays.toString(arr2));
// 6. fill(arr,fillElem)
Arrays.fill(n3, 1);
System.out.println(Arrays.toString(n3));
// 7. equals(arr1,arr2)
System.out.println(Arrays.equals(n2, n3));
// 8. asList
// (1):asList 方法,将 (2,3,45,5) 转成一个集合
// (2):编译类型:List(接口)
// (3):运行类型:java.util.Arrays$ArrayList:是 Arrays 的静态内部类 ArrayList
List asList = Arrays.asList(2, 3, 45, 5);
System.out.println("asList:" + asList);
System.out.println("asList 运行类型:" + asList.getClass());
}
public static void bubbleSort(int[] arr1, Comparator c) {
int temp = 0;
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1.length - i - 1; j++) {
if (c.compare(arr1[j], arr1[j + 1]) > 0) {
temp = arr1[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = temp;
}
}
}
}
}
public class SystemDemo {
public static void main(String[] args) {
// 1. exit
// 0:表示程序退出的状态:正常退出
// System.exit(0);
// 2. arraycopy
// 参数:
// src:原数组
// srcPos:原数组复制起始位置
// dest:目标数组
// destPos:目标数组复制起始位置
// length:复制的元素长度
int[] n1 = {1, 2, 3};
int[] n2 = new int[3];
System.arraycopy(n1, 0, n2, 0, 1);
for (int i = 0; i < n2.length; i++) {
System.out.println(n2[i]);
}
// 3. currentTimeMillis:格林尼治时间
System.out.println(System.currentTimeMillis());
// 4. gc
System.gc();
}
}
应用场景:
1):BigInteger 适合保存比较大的整型
2):BigDecimal 适合保存精度更高的浮点型(小数)
常用方法:
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal("161618.12222222222222222222");
BigDecimal bigDecimal2 = new BigDecimal("161618.122222222222222");
System.out.println(bigDecimal2.add(bigDecimal1));
System.out.println(bigDecimal2.subtract(bigDecimal1));
System.out.println(bigDecimal2.multiply(bigDecimal1));
System.out.println(bigDecimal2.divide(bigDecimal1)); // 可能会报异常 Non-terminating decimal expansion
// 因为碰到除不尽,无限循环,精度又很大,就异常:不可终止的小数扩展
}
}
import java.math.BigInteger;
public class BigIntegerDemo {
public static void main(String[] args) {
BigInteger bigInteger1 = new BigInteger("155646846846846");
BigInteger bigInteger2 = new BigInteger("155646846846846");
System.out.println(bigInteger2.add(bigInteger1));
System.out.println(bigInteger2.subtract(bigInteger1));
System.out.println(bigInteger2.multiply(bigInteger1));
System.out.println(bigInteger2.divide(bigInteger1));
}
}
常见方法:
1.now:静态方法,类调用,获取日期或时间或日期加时间字段
2.getYear()
3.getMonth():返回月份英文
4.getMonthValue():返回月份数字
5.getDayOfMonth():返回天
6.getHour()
7.getMinute()
8.getSecond()
类似于 SimpleDateFormat
y 年 M 月 d 日 h 时 (12) H 时 (24) m 分 s 秒 E 星期几
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.chrono.ChronoLocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws ParseException {
// 第一代:Date
// 1.创建 Date 对象
// 无参创建
System.out.println("=====第一代日期类 Date=====");
Date d1 = new Date();
System.out.println("d1 = " + d1);
// 以毫秒数创建 Date
Date d2 = new Date(1135153135);
System.out.println("d2 = " + d2);
// SimpleDateFormat 格式化日期类
//(1):将 Date 对象格式化为字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(d1);
System.out.println("Date 对象格式化为字符串: " + format);
//(2):将字符串转化为对象
String s = "1986-01-01 17:56:47";
Date parse = sdf.parse(s); // sdf 的格式化规则和字符串 s 不匹配,会报转化异常
System.out.println("字符串转化为 Date 对象: " + parse);
// 第二代日期类:Calendar
System.out.println("=====第二代日期类 Calendar=====");
Calendar c = Calendar.getInstance();
System.out.println("c = " + c);
System.out.println(Calendar.YEAR);
System.out.println(Calendar.MONTH);
System.out.println(Calendar.DAY_OF_MONTH);
System.out.println(Calendar.HOUR);
System.out.println(Calendar.HOUR_OF_DAY);
System.out.println(Calendar.MINUTE);
System.out.println(Calendar.SECOND);
// 第三代日期类:LocalDateTime LocalDate LocalTime
LocalDateTime ldt = LocalDateTime.now();
LocalDate ld = LocalDate.now();
LocalTime lt = LocalTime.now();
System.out.println(ldt.getYear());
System.out.println(ldt.getMonth());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getYear());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
// 格式化日期类:DateTimeFormatter
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format1 = dtf.format(ldt);
System.out.println("格式化后的字符串: " + format1);
// 时间戳:Instant
//(1):Date 转化为 Instant
Date d3 = new Date();
Instant instant = d3.toInstant();
System.out.println("Date 转化为时间戳: " + instant);
//(2):Instant 转化为 Date
Date d4 = Date.from(instant);
System.out.println("时间戳转化为 Date 对象: " + d4);
// 提供 plus 和 minus 对当前时间进行加或减
// 应用:如查看历史订单
LocalDateTime ldt1 = LocalDateTime.now();
LocalDateTime newldt = ldt1.plusDays(586);
System.out.println(newldt);
}
}

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online