Java常用类
1. 包装类
1.1 包装类的概述
java是面向对象的语言,但不是“纯面向对象”,基本数据类型就不是对象。但是我们在实际使用中经常需要将基本数据转化成对象,便于操作。比如:Object[]数组操作中,我们就需要将基本类型数据转化成对象!
为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。
包装类均位于java.lang包中,以下是包装类和基本数据类型的对应关系:
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
在这八个类名中,除了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截图,其它包装类的构造方法基本相同。
【示例】实例化包装对象案例
// 基本数据类型转化为包装类对象
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 字符串转基本类型
| 包装类 | 静态方法 | 方法描述 |
|---|---|---|
| Byte | static byte parseByte(String s) | 将字符串参数解析为带符号的十进制byte 。 |
| Short | static short parseShort(String s) | 将字符串参数解析为带符号的十进制short 。 |
| Integer | static int parseInt(String s) | 将字符串参数解析为带符号的十进制int。 |
| Long | static double parseDouble(String s) | 将字符串参数解析为带符号的十进制long。 |
| Float | static float parseFloat(String s) | 返回一个新 float值,该值被初始化为用指定字符串表示的值。 |
| Double | static double parseDouble(String s) | 返回一个新 double值,该值被初始化为用指定字符串表示的值。 |
| Boolean | static 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() | 返回对象的字符串表示形式。 |
| Byte | static String toString(byte b) | 把byte类型转化为字符串返回。 |
| Short | static String toString(short s) | 把short类型转化为字符串返回。 |
| Integer | static String toString(int i) | 把int类型转化为字符串返回。 |
| Long | static String toString(long i) | 把long类型转化为字符串返回。 |
| Float | static String toString(float f) | 把float类型转化为字符串返回。 |
| Double | static String toString(double d) | 把double类型转化为字符串返回。 |
| Boolean | static String toString(boolean b) | 把boolean类型转化为字符串返回。 |
| Character | static 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;
包装类空指针异常错误
以上代码运行结果之所以会出现空指针异常,是因为该代码相当于:
// 把null赋值类i变量,是一个合法的操作
Integer i = null;
// 对空对象i执行intValue()方法,抛出空指针异常
int j = i.intValue();
null表示i没有指向任何对象的实体,但作为对象名称是合法的(不管这个对象名称存是否指向了某个对象的实体)。由于实际上i并没有指向任何对象的实体,所以也就不可能操作intValue()方法,这样上面的写法在运行时就会抛出NullPointerException异常。
1.5 整数进制转换
1.5.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
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