5168 字
26 min
0

常用类

在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

基本数据类型的包装类

  1. 在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。
  2. 包装类均位于java.lang包中。
  3. 在这八个包装类中,除了Character和Boolean之外都是“数值型”,数值型是java.lang.Number的子类。
  4. Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法:byteValue()、shortValue()、intValue()、longValue()、floatValue()、doubleValue(),意味着所有的数值型包装类都可以互相转型。
  5. 包装类用于实现“基本数据类型”和“引用数据类型”之间的转换,这样就方便涉及到对象的操作,如Object[]、集合等的操作。
  6. 通过包装类的属性,可以获得整数型表示的最大值和最小值,通过包装类提供的方法,用于实现基本数据类型、包装类和字符串之间的相互转换。

基本类型&包装类

基本数据类型 → 包装类

  1. 可以通过包装类提供的构造方法,把基本类型或字符串类型转化为包装类对象。
  2. 通过包装类的valueOf()静态方法,也能把字符串或基本数据类型转化为包装类对象。
  3. 针对Character类型,则字符串不能转化为Character类型的包装对象,只能把char类型的数据转化为Character类型的包装对象。
  4. 针对Boolean类型,只有字符串为“true”(不区分大小写)的时候,转化为包装对象的值才为true,否则一律都返回false。
  5. 在数值型的包装类中(排除Character和Boolean),“字符串内容的格式”必须和“包装类对象基本数据类型的格式”保持一致,否则抛出NumberFormatException异常。

Integer i1 = new Integer(12);
Integer i2 = new Integer("123");
 
Integer i1 = Integer.valueOf(123);
Integer i2 = Integer.valueOf("123");

包装类 → 基本数据类型

  1. 数值型包装类是java.lang.Number的子类,Number类提供了抽象方法:byteValue()、shortValue()、intValue()、longValue()、floatValue()、doubleValue(),意味着所有的数值型包装类都可以互相转型。
  2. 非数值型包装类中,Boolean类型对象只能转化为boolean类型,因为它只有booleanValue()方法;Character类型对象只能转化为char类型,因为它只有charValue()方法。

// 实例化一个包装类对象
Double d = new Double("1.23");
 
// 获取包装对象中的int数值
int num = d.intValue();
// 获取包装对象中的double数值
double dou = d.doubleValue();
// 输出:num:1 , dou:1.23
System.out.println("num:" + num + " , dou:" + dou);

基本类型&字符串

字符串 → 基本类型

  1. 通过包装类中的静态方法parseXXX,把字符串转化成基本数据类型。
  2. 不能把字符串转化为char类型,因为Character类型中没有提供parseChar(String value)方法。
  3. 针对Boolean类型,只有字符串为“true”(不区分大小写)的时候,转化为基本类型的值才为true,否则一律都返回false。
  4. 在数值型的包装类中,“字符串内容的格式”必须和“包装类对象基本数据类型的格式”保持一致,否则抛出NumberFormatException异常。

// 字符串转double基本数据类型
System.out.println(Double.parseDouble("123.4") + 0.6); // 输出:124.0
// 字符串转int基本数据类型
System.out.println(Integer.parseInt("123") + 77); // 输出:200

基本类型 → 字符串

通过包装类中的静态方法,也就是toString()方法,就能把基本数据类型转化成字符串。


// 把int类型转化成字符串
System.out.println(Integer.toString(123) + "A"); // 输出:"123A"
// 把double类型转化为字符串
System.out.println(Double.toString(123.4) + "A"); // 输出:"123.4A"
// 把char类型转化成字符串
System.out.println(Character.toString('A') + "A"); // 输出:"AA"

自动装箱拆箱

  1. 自动装箱和拆箱就是将基本类型和包装类进行自动的互相转换。JDK1.5后,将自动装箱(autoboxing)和拆箱(unboxing)引入java中。
  2. 当基本类型数据处于需要对象的环境中时,则就会触发自动装箱机制,也就是自动把基本数据类型转化为包装类对象。当对象处于需要基本数据类型的环境中,则就会触发自动拆箱机制,也就是自动把包装类对象转化为基本数据类型。
  3. JDK1.5 后,Integer i = 5 等价于 Integer i = Integer.valueOf(5)。
  4. 自动装箱过程是通过调用包装类的valueOf()方法实现的,而自动拆箱过程是通过调用包装类的xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)。

自动装箱缓存问题

  1. 针对整数型的包装类,如果整数值在[-128, 127]之间时,那么触发自动装箱机制的时候,默认会从“缓冲池”中取出一个包装类对象并返回,而不会创建一个新的包装类对象并返回。
  2. 如果整数值在[-128, 127]之外时,那么触发自动装箱机制的时候,则就会创建一个新的包装类对象并返回,而不会从“缓冲池”中取出一个包装类对象并返回。
  3. 通过IntegerCache这个静态内部类,实现对[-128, 127]之间的数值进行缓存处理。

空指针异常问题

Integer integer = null;
int num = integer ;

image-20250826164624416

以上代码运行结果之所以会出现空指针异常,是因为该代码相当于:

// 把null赋值类integer变量,是一个合法的操作
Integer integer = null;
// 对空对象integer执行intValue()方法,抛出空指针异常
int num = integer.intValue();

由于实际上integer并没有指向任何对象的实体,所以也就不可能操作intValue()方法,否则就会抛出NullPointerException异常。

整数进制转换

【示例】十进制转别的进制案例

// 需求:十进制转化为二进制
System.out.println(Integer.toBinaryString(4));  // 输出:100
// 需求:十进制转化为八进制
System.out.println(Integer.toOctalString(9));   // 输出:11
// 需求:十进制转化为十六进制
System.out.println(Integer.toHexString(17));    // 输出:11

【示例】别的进制转十进制案例

// 需求:二进制转化为十进制
System.out.println(Integer.parseInt("100010", 2)); // 输出:34
// 需求:八进制转化为十进制
System.out.println(Integer.parseInt("017", 8)); // 输出:15
// 需求:十六进制转化为十进制
System.out.println(Integer.parseInt("2B", 16)); // 输出:43

Java大数字运算

BigInteger类

  1. 由于java语言中的long类型表示整数数据范围有限,若希望描述更大的整数数据时,就需要借助java.math.BigInteger类型加以描述。
  2. 可以使用BigInteger的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigInteger对象。
  3. 因为BigInteger所创建的是对象,我们不能使用传统的+、-、*、/、%等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法,方法中的参数也必须是BigInteger的对象。
  4. 进行传统的+、-、*、/、%等算术运算后,我们可能需要将BigInteger对象转换成相应的基本数据类型的变量,可以使用intValue(),doubleValue()等方法。
  5. BigInteger类没有缓存机制。

// 实例化两个BigInteger对象
BigInteger d1 = new BigInteger("5");
BigInteger d2 = new BigInteger("2");
 
// 加法运算
BigInteger addNum = d1.add(d2);
System.out.println("加法运算:" + addNum); // 输出:7
 
// 减法运算
BigInteger subtractNum = d1.subtract(d2);
System.out.println("减法运算:" + subtractNum); // 输出:3
 
// 乘法运算
BigInteger multiplyNum = d1.multiply(d2);
System.out.println("乘法运算:" + multiplyNum); // 输出:10
 
// 除法运算
BigInteger divideNum = d1.divide(d2);
System.out.println("除法运算:" + divideNum); // 输出:2
 
// 取余运算
BigInteger[] result = d1.divideAndRemainder(d2);
// 输出:商:2 余数:1
System.out.println("商:" + result[0] + " 余数:" + result[1]);

BigDecimal类

  1. float和double类型的主要设计目标是为了科学计算和工程计算,双精度浮点型变量double可以处理16位有效数,然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。
  2. 商业计算往往要求结果精确,这时候java.math.BigDecimal类就派上大用场啦。BigDecimal由任意精度的整数非标度值和32位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以10的负 scale 次幂。
  3. 构造一个浮点型的BigDecimal对象,参数类型为double的构造方法的结果有一定的不可预知性,而String 构造方法是完全可预知的,所以尽量使用参数类型为String的构造函数。
  4. 可以使用BigDecimal的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigDecimal对象。
  5. 因为BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法,方法中的参数也必须是BigDecimal的对象。
  6. 进行传统的+、-、*、/等算术运算后,我们可能需要将BigDecimal对象转换成相应的基本数据类型的变量,可以使用floatValue(),doubleValue()等方法。

// 参数类型为double的构造方法
BigDecimal aDouble = new BigDecimal(1.22);
// 输出:aDouble: 1.2199999999999999733546474089962430298328399658203125
System.out.println("aDouble: " + aDouble);
 
// 参数类型为String的构造方法,建议使用
BigDecimal aString = new BigDecimal("1.22");
// 输出:aString: 1.22
System.out.println("aString: " + aString);

String类

  1. String类对象代表不可变的Unicode字符序列。
  2. 字符串内容全部存储到value[]数组中,而且该数组是final类型,也就是常量(即只能被赋值一次),这就是“不可变对象”的典型定义方式。
    • 底层是数组,所以字符串长度不能变
    • 使用final修饰,所以该数组不能改变
    • 使用private修饰,所以无法在外部获取到该数组,然后使用下标对数组元素进行修改
  3. 虽然字符串本身不能改变,但是String类型变量中记录的地址值是可以改变的。

public static void main(String[] args) {
	// 方法栈中的str指向堆中的某个地址
	String str = new String("bjpowernode");
	// 方法栈中的str指向堆中的另一个地址
	str = "bjpowernode";
}

String类构造方法

// 1.创建一个空字符串
String str1 = new String(); // 存储内容:""
// 2.通过常量字符串来创建字符串
String str2 = new String("bjpowernode"); // 存储内容:"bjpowernode"
 
// 3.通过byte数组来创建字符串
byte[] bytes = new byte[] {65, 66, 67, 68, 69}; 
// 3.1把byte数组全部元素作为字符串的内容来创建字符串
String str3 = new String(bytes); // 存储内容:"ABCDE"
 
// 4.通过char数组来创建字符串
char[] chars = new char[] {'a', 'b', 'c', 'd', 'e'};
// 4.1把char数组全部元素作为字符串的内容来创建字符串
String str4 = new String(chars); // 存储内容:"abcde"

【示例】两种字符串创建方式的区别

// 通过双引号创建字符串
String str1 = "hello world";
// 通过构造方法创建字符串
String str2 = new String("hello world");
// 比较地址
System.out.println(str1 == str2); // 输出:false
// equals方法比较字符串内容
System.out.println(str1.equals(str2)); // 输出:true

str1 和 str2 的创建方式有什么不同呢?

  1. str1创建,在内存中只有一个对象,这个对象在字符串常量池中。
  2. str2创建,在内存中有两个对象。一个new的对象在堆中,一个字符串本身对象,在字符串常量池中。

String类查找方法

获取字符串长度

String str = new String("bjpowernode");
int length = str.length();
System.out.println("length:" + length); // 输出:5

charAt方法

charAt()方法返回指定索引位置的char值,索引范围为0 ~ length() – 1,如果索引越界,则抛出StringIndexOutOfBoundsException异常。

String str = new String("bjpowernode");
// 注意:索引范围为[0, 字符串长度)
char c1 = str.charAt(3);
System.out.println(c1); // 输出:'x'
// 如果索引越界,抛出StringIndexOutOfBoundsException异常
char c2 = str.charAt(8); // 运行抛出异常

indexOf方法

indexOf方法返回一个整数值,该整数值就是字符或子字符串在指定字符串中所在的位置,如果没有找到则返回-1。如果fromIndex是负数,则fromIndex被当作零,如果它比最大的字符位置索引还大,则它被当作最大的可能索引。


String str = "hello-world-hello-world";
// 1. 获取指定字符在字符串中的第一次出现的位置,如果字符不存在返回-1
int index1 = str.indexOf('o');
System.out.println("index:" + index1); // 输出:4
// 2. 获取指定字符第一次出现在字符串中的位置,以指定的索引开始搜索,如果字符不存在返回-1
int index2 = str.indexOf('o', 5);
System.out.println("index:" + index2); // 输出:7
// 3.获取指定子字符串在字符串中第一次出现的位置,如果字符不存在返回-1
int index3 = str.indexOf("llo");
System.out.println("index:" + index3); // 输出:2
// 4.获取指定字符串第一次出现的字符串中的位置,以指定的索引开始搜索,如果字符不存在返回-1
int index4 = str.indexOf("llo", 9);
System.out.println("index:" + index4); // 输出:14

lastIndexOf方法

lastIndexOf方法返回一个整数值,该整数值就是字符或子字符串在指定字符串中所在的位置,如果没有找到则返回-1。如果fromIndex是负数,则fromIndex被当作零,如果它比最大的字符位置索引还大,则它被当作最大的可能索引。


String str = "hello-world-hello-world";
// 1.获取指定字符在字符串中的最后一次出现的位置,如果字符不存在返回-1
int index1 = str.lastIndexOf('o'); 
System.out.println("index:" + index1); // 返回:19
// 2.获取指定字符最后一次出现在字符串中的位置,以指定的索引开始搜索,如果字符不存在返回-1
int index2 = str.lastIndexOf('o', 15);
System.out.println("index:" + index2); // 返回:7
// 3.获取指定子字符串在字符串中最后一次出现的位置,如果字符不存在返回-1
int index3 = str.lastIndexOf("llo");
System.out.println("index:" + index3); // 返回:14
// 4.获取指定字符串最后一次出现在字符串中的位置,以指定的索引开始搜索,如果字符不存在返回-1
int index4 = str.lastIndexOf("llo", 9);
System.out.println("index:" + index4); // 返回:2

startsWith方法

startsWith(String prefix)方法,判断字符串是否以指定字符串开头,返回值为boolean类型。


String url = "http://www.bjpowernode.com";
// 判断url是否采用的http:协议,就是判断字符串是否以"http:"开头
boolean flag = url.startsWith("http:");
System.out.println("flag:" + flag); // 输出:true

endsWith方法

endsWith(String prefix)方法,判断字符串是否以指定字符串结尾,返回值为boolean类型。


String url = "http://www.bjpowernode.com";
// 判断网站域名是否是.cn域名,也就是判断字符串是否以.cn结尾
boolean flag = url.endsWith(".cn");
System.out.println("flag:" + flag); // 输出:false

contains方法

contains(CharSequence s)方法,判断字符串中是否包含指定字符串,返回值为boolean类型。


String url = "http://www.bjpowernode.com";
// 判断字符串中是否包含"bjpowernode"
boolean flag = url.contains("bjpowernode");
System.out.println("flag:" + flag); // 输出:true

String类转换方法

字符串转数组

  • String[] split(String regex):将一个字符串分割为子字符串,并返回字符串数组。
  • char[] toCharArray():将此字符串转换为新的字符数组。
  • byte[] getBytes():得到一个操作系统默认的编码格式的字节数组。

字符串大小写转换

  • String toUpperCase():返回一个新的字符串,该字符串中所有英文字符转换为大写字母。
  • String toLowerCase():返回一个新的字符串,该字符串中所有英文字符转换为小写字母。

忽略字符串前后空格

String trim():返回一个新的字符串,该字符串中去掉了前后的空格。

字符串的截取

  • String substring(int beginIndex):从beginIndex开始截取字符串,到字符串末尾结束。如果 beginIndex的值为负或大于字符串长度,则抛出IndexOutOfBoundsException异常。
  • String substring(int beginIndex, int endIndex):从beginIndex开始截取字符串,到字符索引endIndex-1结束。如果beginIndex为负,或endIndex大于字符串长度,或beginIndex大于endIndex,则抛出IndexOutOfBoundsException异常。

字符串的替换

  • String replace(char oldChar, char newChar):通过用newChar字符替换字符串中出现的所有oldChar字符,并返回替换后的新字符串。
  • String replace(CharSequence target, CharSequence replacement):将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列。

字符串的拼接

// 字符串拼接,功能和“+”连接符相似
String str = "hello".concat(" world");
// 输出:"hello world"
System.out.println(str);
  1. 功能上:"hello".concat(" world")"hello" + " world" 是等价的,结果相同。
  2. concat() 只会处理非空字符串。如果参数为 null,会抛出 NullPointerException。
  3. "hello".concat(" world") 不会被编译器优化为常量。每次调用 concat() 方法时,都会创建一个新的字符串对象。
  4. 直接调用 Stringconcat() 方法,内部实现是通过数组拷贝来完成字符串拼接。它比使用 StringBuilder 更轻量,但不如编译期常量优化高效。

String类其他方法

isEmpty方法

boolean isEmpty()方法,判断字符串内容是否为空。当字符串长度为0,则返回true,否则返回false。

equals方法

String str = "hello world";
// 判断字符串内容是否相同
boolean flag1 = str.equals("hello WORLD");
System.out.println(flag1); // 输出:false
// 判断字符串内容是否相同,忽略大小写
boolean flag2 = str.equalsIgnoreCase("hello WORLD");
System.out.println(flag2); // 输出:true

valueOf方法

valueOf方法是一个静态方法,可以把基本数据类型转化为字符串类型,是类型转换中非常重要的一个方法。

intern方法

  1. intern() 是 String 类中的一个本地方法,它用于字符串池(String Pool)的管理。通过 intern() 方法,可以确保字符串在 JVM 的字符串常量池中只存在一份拷贝,从而节省内存并提高性能。
  2. 当调用 intern() 方法时,如果字符串常量池中已经包含了该字符串,则返回池中的引用;否则,将此字符串添加到字符串常量池中,并返回指向该字符串的引用。

StringBuffer类

  1. String类代表不可变的Unicode字符序列,是字符串常量。String字符串一旦被初始化后,就不能再被改变其内容了(其原理在String类概述中已经讲述)。对String字符串的操作实际上对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。
  2. 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,从而降低了程序的效率。
  3. StringBuffer类是抽象类AbstractStringBuilder的子类,StringBuffer类代表可变的Unicode字符序列,是字符串变量。
  4. AbstractStringBuilder内部也是一个字符数组,但是这个字符数组没有用final修饰,那么意味着我们可以随时修改,所以我们又称StringBuffer为“可变字符序列”。因为StringBuffer类是对原字符串本身进行操作的,对字符串进行修改操作而不产生副本拷贝,效率较高。

StringBuffer类构造方法

  • StringBuffer():构造一个没有字符的字符串缓冲区,初始容量为16个字符。
  • StringBuffer(CharSequence seq):构造一个包含与指定的相同字符的字符串缓冲区CharSequence。
  • StringBuffer(int capacity):构造一个没有字符的字符串缓冲区和指定的初始容量。
  • StringBuffer(String str):构造一个初始化为指定字符串内容的字符串缓冲区。

相关文章

评论区