Java常用类--包装类

193 阅读14分钟

Java常用类

1. 包装类

1.1 包装类的概述

java是面向对象的语言,但不是“纯面向对象”,基本数据类型就不是对象。但是我们在实际使用中经常需要将基本数据转化成对象,便于操作。比如:Object[]数组操作中,我们就需要将基本类型数据转化成对象!

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

包装类均位于java.lang包中,以下是包装类和基本数据类型的对应关系:

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

在这八个类名中,除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。

在这八个包装类中,除了Character和Boolean之外都是“数值型”,数值型是java.lang.Number的子类。Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法:byteValue()、shortValue()、intValue()、longValue()、floatValue()、doubleValue(),意味着所有的数值型包装类都可以互相转型

对于包装类说,这些类的用途主要包含两种:

1、 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如Object[]、集合等的操作。

2、 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化)。

1.2 基本类型&包装类

1.2.1 基本类型转包装类

我们可以通过包装类提供的构造方法,可以把基本类型或字符串类型转化为包装对象。下面以Integer构造方法API截图,其它包装类的构造方法基本相同。

image.png 【示例】实例化包装对象案例

// 基本数据类型转化为包装类对象
Integer i1 = new Integer(12);
Float f2 = new Float(1.23);
// 字符串转化为包装类对象
Integer i2 = new Integer("123");
Float f2 = new Float("1.23")

我们还可以通过包装类的valueOf()静态方法,把字符串或基本数据类型转化为包装对象。

【示例】基本类型或字符串类型转化为包装对象

// 基本数据类型转化为包装类型对象
Double f1 = Double.valueOf(1.23);
Integer i1 = Integer.valueOf(123);
// 字符串类型转化为包装类型对象
Double f2 = Double.valueOf("1.23");
Integer i2 = Integer.valueOf("123");

基本类型转换成包装对象,注意事项:

1、针对Character类型,字符串不能转化为Character类型的包装对象。

2、针对Boolean类型,只有字符串为“true”(不区分大小写)的时候,转化为包装对象的值才为true,否则都为false。

3、数值型的包装类中(不包含Character和Boolean),形参字符串的内容为必须为数值型,否则抛出NumberFormatException异常。

1.2.2 包装类转基本类型

数值型包装类是java.lang.Number的子类,Number类提供了抽象方法:byteValue()、shortValue()、intValue()、longValue()、floatValue()、doubleValue(),意味着所有的数值型包装类都可以互相转型。

【示例】数值型包装对象转化为基本类型

// 实例化一个包装类对象
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);

非数值型包装类中,Boolean类型对象只能转化为boolean类型,因为它只有booleanValue()方法;Character类型对象只能转化为char类型,因为它只有charValue()方法。

【示例】非数值型包装对象转化为基本类型

// Boolean对象转化为boolean类型
Boolean b = new Boolean("true");
boolean flag = b.booleanValue();
System.out.println("flag:" + flag); // 输出:flag:true
// Character对象转化为char类型
Character c = new Character('A');
char cc = c.charValue();
System.out.println("char:" + cc); // 输出:char:A

1.3 基本类型&字符串

1.3.1 字符串转基本类型

包装类静态方法方法描述
Bytestatic byte parseByte(String s)将字符串参数解析为带符号的十进制byte 。
Shortstatic short parseShort(String s)将字符串参数解析为带符号的十进制short 。
Integerstatic int parseInt(String s)将字符串参数解析为带符号的十进制int。
Longstatic double parseDouble(String s)将字符串参数解析为带符号的十进制long。
Floatstatic float parseFloat(String s)返回一个新 float值,该值被初始化为用指定字符串表示的值。
Doublestatic double parseDouble(String s)返回一个新 double值,该值被初始化为用指定字符串表示的值。
Booleanstatic boolean parseBoolean(String s)将字符串参数解析为boolean值。

【示例】字符串转基本类型案例

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

注意事项:

1、 不能把字符串转化为char类型,因为没有parseChar(String value)方法。

2、 针对Boolean类型,只有字符串为“true”的时候,转化为基本类型的值才为true,否则都为false。

3、 整数型包装类,字符串中的内容必须是十进制整数;浮点型包装类中,字符串中的内容必须为十进制整数或浮点数,否则抛出NumberFormatException异常。

1.3.2 基本类型转字符串

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

包装类方法方法描述
所有包装类String toString()返回对象的字符串表示形式。
Bytestatic String toString(byte b)把byte类型转化为字符串返回。
Shortstatic String toString(short s)把short类型转化为字符串返回。
Integerstatic String toString(int i)把int类型转化为字符串返回。
Longstatic String toString(long i)把long类型转化为字符串返回。
Floatstatic String toString(float f)把float类型转化为字符串返回。
Doublestatic String toString(double d)把double类型转化为字符串返回。
Booleanstatic String toString(boolean b)把boolean类型转化为字符串返回。
Characterstatic String toString(char c)把char类型转化为字符串返回。

【示例】基本数值转成字符串案例

// 把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.4 自动装箱拆箱(重点)

自动装箱和拆箱就是将基本类型和包装类进行自动的互相转换。JDK1.5后,将自动装箱(autoboxing)和拆箱(unboxing)引入java中。

1.4.1 自动装箱和自动拆箱

基本类型数据处于需要对象的环境中时,会自动转为“对象”,这就称为自动装箱

我们以Integer为例:在JDK1.5以前,这样的代码 Integer i = 5 是错误的,必须要通过Integer i = new Integer(5) 这样的语句来实现基本数据类型转换成包装类的过程;而在JDK1.5以后,Java提供了自动装箱的功能,因此只需Integer i = 5这样的语句就能实现基本数据类型转换成包装类,这是因为JVM为我们执行了Integer i = Integer.valueOf(5)这样的操作,这就是Java的自动装箱。

【示例】自动装箱案例

Integer i1 = 100; // 自动装箱
// 相当于编译器自动为您作以下的语法编译:
Integer i2 = Integer.valueOf(100); // 调用的是valueOf(100),而不是new Integer(100)

通过自动装箱特性,我们可以用Object数组来存放基本数据类型数据。

// 存放基本数据类型的数组(自动装箱)
Object[] arr = {11.1, 18, 12, 11.1};

每当需要一个值时,对象会自动转成基本类型数据, 没必要再去显式调用intValue、doubleValue()等转型方法,这就是自动拆箱。

自动装箱过程是通过调用包装类的valueOf()方法实现的,而自动拆箱过程是通过调用包装类的 xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)。

【示例】自动拆箱案例

Integer i = 100; // 自动装箱
int j = i; // 自动拆箱
// 相当于编译器自动为您作以下的语法编译:
int j1 = i.intValue();

1.4.2 自动装箱缓存问题

在JDK1.5自动装箱时,对于整数型的包装类(Byte、Short、Integer、Long类型),如果数值在byte(-128-127)范围之内,为了提高效率Integer类会进行缓存处理,不会新创建对象空间而是使用原来已有的空间。当数值超出byte范围之外,就不会对Integer类进行缓存处理了。

Integer类相关源码如下:

public static Integer valueOf(int i) {
     if (i >= IntegerCache.low && i <= IntegerCache.high)
          return IntegerCache.cache[i + (-IntegerCache.low)];
     return new Integer(i);
}

通过IntegerCache这个静态内部类,实现对-128~127之间的值会进行缓存处理。

【示例】自动装箱缓存案例

Integer a = 12;
Integer b = 12;
// 未超出 byte 范围,新建的对象会进行缓存处理,a和b指向同一块地址
System.out.println(a == b); // 输出:true
// 包装类中的equals方法,只比较的是内容值
System.out.println(a.equals(b));  // 输出:true
​
Integer c = 128;
Integer d = 128;
// 超出 byte 范围,新建的对象不会进行缓存处理,c和d是指向不同的地址
System.out.println(c == d); // 输出:false
System.out.println(c.equals(d)); // 输出:true

扩展:尝试着模拟实现Integer类。

1.4.3 空指针异常

【示例】包装类空指针异常案例

Integer i = null;
14 int j = i;

image.png 包装类空指针异常错误

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

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

null表示i没有指向任何对象的实体,但作为对象名称是合法的(不管这个对象名称存是否指向了某个对象的实体)。由于实际上i并没有指向任何对象的实体,所以也就不可能操作intValue()方法,这样上面的写法在运行时就会抛出NullPointerException异常。

1.5 整数进制转换

1.5.1 十进制转别的进制

我们可以通过Integer类提供的静态方法实现进制之间的转换。

包装类方法作用
Integerstatic String toBinaryString(int i)把十进制转化为2进制
Integerstatic String toOctalString(int i)把十进制转化为8进制
Integerstatic String toHexString(int i)把十进制转化为16进制

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

// 十进制转2进制
System.out.println(Integer.toBinaryString(4)); // 输出:100
// 十进制转8进制
System.out.println(Integer.toOctalString(9)); // 输出:11
// 十进制转16进制
System.out.println(Integer.toHexString(17)); // 输出:11

1.5.2 别的进制转十进制

通过Integer类的static int parseInt(String str, int radix)方法,把别的进制转化为十进制。

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

// 2进制转化为十进制
System.out.println(Integer.parseInt("100", 2)); // 输出:4
// 8进制转化为十进制
System.out.println(Integer.parseInt("11", 8)); // 输出:9
// 16进制转化为十进制
System.out.println(Integer.parseInt("1a", 16));; // 输出:26

1.6 Java大数字运算

1.6.1 BigInteger类

由于java语言中的long类型表示整数数据范围有限,若希望描述更大的整数数据时,就需要借助java.math.BigInteger类型加以描述。BigInteger类属于java.math包中,因此在每次使用前都要import 这个类。

BigInteger类部分构造方法摘要
BigInteger(String val)创建一个具有参数所指定以字符串表示的数值的对象。

【示例】BigInteger类的构造方法

// 参数类型为String的构造方法
BigInteger bd = new BigInteger("111111");
// 输出:111111
System.out.println(bd);

一般来说,可以使用BigInteger的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigInteger对象。

因为BigInteger所创建的是对象,我们不能使用传统的+、-、*、/、%等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法,方法中的参数也必须是BigInteger的对象。

BigInteger类数学运算方法摘要
BigInteger add(BigInteger augend)加法运算
BigInteger subtract(BigInteger subtrahend)减法运算
BigInteger multiply(BigInteger multiplicand)乘法运算
BigInteger divide(BigInteger divisor)除法运算
BigInteger[] divideAndRemainder(BigInteger val)求余运算

【示例】BigInteger类的数学运算方法

进行传统的+、-、*、/、%等算术运算后,我们可能需要将BigInteger对象转换成相应的基本数据类型的变量,可以使用intValue(),doubleValue()等方法。

// 实例化两个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]);

【示例】BigInteger类型转化为基本数据类型

// 实例化两个BigInteger对象
BigInteger d1 = new BigInteger("5");
BigInteger d2 = new BigInteger("2");
// 加法运算
BigInteger addNum = d1.add(d2);
// 把BigInteger类型转化为int类型
int num = addNum.intValue();
System.out.println(num); // 输出:7
// 减法运算
BigInteger subtractNum = d1.subtract(d2);
// 把BigInteger类型转化为double类型
double d = subtractNum.doubleValue();
System.out.println(d); // 输出:3.0

1.6.2 BigDecimal

float和double类型的主要设计目标是为了科学计算和工程计算,双精度浮点型变量double可以处理16位有效数,然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。

【示例】浮点型无法精确提供运算结果案例

// 输出结果为:3.0000000000000004E-8
System.out.println(0.00000001 + 0.00000002);

但是商业计算往往要求结果精确,这时候java.math.BigDecimal类就派上大用场啦。BigDecimal由任意精度的整数非标度值和32位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以10的负scale 次幂。

*BigDecimal *类部分构造方法摘要
BigDecimal(double val)创建一个具有参数所指定双精度值的对象。
BigDecimal(int val)创建一个具有参数所指定整数值的对象。
BigDecimal(long val)创建一个具有参数所指定长整数值的对象。
BigDecimal(String val)创建一个具有参数所指定以字符串表示的数值的对象。

构造一个浮点型的BigDecimal对象,参数类型为double的构造方法的结果有一定的不可预知性,而String 构造方法是完全可预知的,所以尽量使用参数类型为String的构造函数。

【示例】BigDecimal类的构造方法

// 参数类型为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);

一般来说,可以使用BigDecimal的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigDecimal对象。

因为BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法,方法中的参数也必须是BigDecimal的对象。

BigDecimal类数学运算方法摘要
BigDecimal add(BigDecimal augend)加法运算
BigDecimal subtract(BigDecimal subtrahend)减法运算
BigDecimal multiply(BigDecimal multiplicand)乘法运算
BigDecimal divide(BigDecimal divisor)除法运算

【示例】BigDecimal类的数学运算方法

// 实例化两个BigDecimal对象
BigDecimal d1 = new BigDecimal("3.0");
BigDecimal d2 = new BigDecimal("2.0");
// 加法运算
BigDecimal addNum = d1.add(d2);
System.out.println("加法运算:" + addNum); // 输出:5.0
// 减法运算
BigDecimal subtractNum = d1.subtract(d2);
System.out.println("减法运算:" + subtractNum); // 输出:1.0
// 乘法运算
BigDecimal multiplyNum = d1.multiply(d2);
System.out.println("乘法运算:" + multiplyNum); // 输出:6.00
// 除法运算
BigDecimal divideNum = d1.divide(d2);
System.out.println("除法运算:" + divideNum); // 输出:1.5

进行传统的+、-、*、/等算术运算后,我们可能需要将BigDecimal对象转换成相应的基本数据类型的变量,可以使用floatValue(),doubleValue()等方法。

【示例】BigDecimal类型转化为基本数据类型

// 实例化两个BigDecimal对象
BigDecimal d1 = new BigDecimal("3.0");
BigDecimal d2 = new BigDecimal("2.0");
// 加法运算
BigDecimal addNum = d1.add(d2);
// BigDecimal类型转化为int类型
int n = addNum.intValue();
System.out.println(n); // 输出:5
// 除法运算
BigDecimal divideNum = d1.divide(d2);
// BigDecimal类型转化为double类型
double d = addNum.intValue();
System.out.println(d); // 输出:5.0