java常用类02_包装类(下)

1.自动装箱拆箱

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

2.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.2自动装箱缓存问题

在 JDK1.5 自动装箱时,如果数值在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.3空指针异常问题

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

Integer i = null;
int j = i;

执行结果如下图所示:
在这里插入图片描述
以上代码运行结果之所以会出现空指针异常,是因为该代码相当于:

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

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

2.整数进制转换

2.1十进制转别的进制

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

包装类 方法 作用
Integer static String toBinaryString(int i) 把十进制转化为2进制
Integer static String toOctalString(int i) 把十进制转化为8进制
Integer static 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

2.2别的进制转十进制

通过Integer类的static int parseInt(String s, 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

3. Java大数字运算

3.1 BigInteger类

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

【示例】BigInteger类的构造方法

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

一般来说,可以使用BigInteger的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成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对象
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对象转换成相应的基本数据类型的变量,可以使用floatValue(),doubleValue()等方法。

【示例】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

3.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(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 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

ps:如需最新的免费文档资料和教学视频,请添加QQ群(627407545)领取。

发布了92 篇原创文章 · 获赞 0 · 访问量 2600

猜你喜欢

转载自blog.csdn.net/zhoujunfeng121/article/details/104752439