关于Java中对包装类的应用
一、为什么要引入包装类?
我们知道,在Java之中所有引用数据类型都可以自动的向Object类对象进行向上转型,这样就可以通过Object实现参数的统一,但是这时我们就会发现一个问题:基本数据类型不属于引用类型,那么这个时候就会发现操作上的偏差,所有为了解决这个问题,早先提出的方案就是利用一自定义的类的形式实现基本数据类型的包装。
范例:使用类结构包装基本数据类型
class IntWrapper { // 做一个包装类
private int data ; // 保存整型数据
public IntWrapper(int data) { // 包装类需要提供有专属的数字信息
this.data = data ;
}
public int intValue() { // 从包装类中返回信息
return this.data ;
}
}
public class Demo {
public static void main(String args[]) {
Object obj = new IntWrapper(3) ; // 将基本数据类型封装在类对象中,随后向上转型
IntWrapper iw = (IntWrapper) obj ; // 强制对象转型
System.out.println(iw.intValue()) ; // 从包装类中获取原始的基本数据类型
}
}
//程序执行结果:3
以上操作形式就是传统设计之中解决Object类对象接受基本数据类型的操作问题,但是既然这些问题都已经知道了,那么作为Java语言本身也一定可以想到,因为Java在设计Object类的时候主要的目的就是为了参数的统一,所以在Java程序的内部提供有类似的包装类,分为两种:
-
对象型包装类(Object直接子类):boolean(Boolean)、char(Character);
-
数值型包装类(Number直接子类):byte(Byte)、short(short)、int(Integer)、long(Long)、float(Float)、double(Double);
Number作为数值型包装类,本身提供了所有基本数据信息的获取方法,这些方法一共有六个。
No | 方法名称 | 类型 | 描述 |
---|---|---|---|
01 | public byte byteValue() | 普通 | 从包装类中获取被包装的byte数据信息 |
02 | public short shortValue() | 普通 | 从包装类中获取被包装的short数据信息 |
03 | public abstract int intValue() | 普通 | 从包装类中获取被包装的int数据信息 |
04 | public abstract long longValue() | 普通 | 从包装类中获取被包装的long数据信息 |
05 | public abstract float floatValue() | 普通 | 从包装类中获取被包装的float数据信息 |
06 | public abstract double doubleValue() | 普通 | 从包装类中获取被包装的double数据信息 |
二、装箱与拆箱
经过之前的分析之后可以发现,Java为了便于基本数据类型与Object类之间的转换处理,提供有装箱与拆箱的机制,所谓的装箱是指将基本数据类型保存在包装类之中,而所谓的拆箱指的是通过包装类获取基本类型对应的数值。
-
装箱操作一般都是使用类中的构造方法完成:
- 【Deprecated:过期的】Integer类构造方法:public Integer(int value);
- JDK 1.9之后的新做法,使用Integer类内部提供的static方法:public static Integer valueOf(int i);
- 【Deprecated:过期的】Double类构造方法:public Double(double value);
- JDK 1.9之后的新做法,使用Double类内部提供的static方法:public static Double valueOf(double d);
- 【Deprecated:过期的】Boolean类构造方法:public Boolean(boolean value);
- JDK 1.9之后的新做法,使用Boolean类内部提供的static方法:public static Boolean valueOf(boolean b);
- 【Deprecated:过期的】Integer类构造方法:public Integer(int value);
-
拆箱操作一般都是使用类中提供的xxxValue()方法完成;
范例:观察传统装箱与拆箱操作
public class Demo { public static void main(String args[]) { Integer num = new Integer(3) ; // 传统装箱:构造方法 int temp = num.intValue() ; // 拆箱:xxxValue()方法 System.out.println(temp * 2) ; } } //程序运行结果:6
通过上个程序可以发现,在之前设计的IntWrapper类就是参照了Integer的功能来实现的,但是在JDK 1.9之后,包装类的构造方法不建议再使用,而是希望使用valueOf()方法实现装箱处理。
范例:观察JDK 1.9之后的装箱操作
public class Demo {
public static void main(String args[]) {
Double num = Double.valueOf(3) ; // JDK 1.9之后的装箱:构造方法
double temp = num.doubleValue() ; // 拆箱:xxxValue()方法
System.out.println(temp * 2) ;
}
}
//程序运行结果:6.0
在所有标准化的程序设计结构中,功能相近的类都应该拥有类似的程序操作结构,不过以上的这些做法都属于JDK 1.5之前的功能了,在JDK 1.5之后提供有更高级的自动拆箱与装箱机制,不再需要明确的通过包装类的方法,就可以自动将一个基本数据类型变为一个与之匹配的包装类对象,同时该对象还可以直接进行数学计算。
范例:自动装箱与拆箱
public class Demo {
public static void main(String args[]) {
Integer numA = 10 ; // 自动装箱
Double numB = 30.5 ; // 自动装箱
numA ++ ; // 包装类直接计算
System.out.println(numA * numB) ; // 包装类直接计算:335.5
}
}
//程序执行结果:335.5
通过此时的代码就可以非常清楚地发现,当前的程序里面已经不需要手工的装箱与拆箱了,这样就极大简化了代码开发的难度,同时这样的操作还有一个最重要的特点:基本数据类型经过自动包装后可以直接向Object转型了。
范例:基本数据类型与Object类的使用
public class Demo {
public static void main(String args[]) {
Object obj = 10.3 ; // 10.3自动由double包装为Double类实例,随后自动向上转型为Object
double num = (Double) obj ; // Object必须先向下转为包装类后才可以自动拆箱
System.out.println(num * 2) ;
}
}
//程序执行结果:20.6
Object可以在JDK 1.5之后彻底实现所有参数的统一,基本数据类型和引用数据类型都可以通过Object接受了,权力无限大!
范例:观察包装类的一个小问题
-
观察Integer比较不超过127值时的情况:
public class Demo { public static void main(String args[]) { Integer numA = 127 ; Integer numB = 127 ; Integer numC = Integer.valueOf(127) ; Integer numD = new Integer(127) ; System.out.println(numA == numB) ; // 对象比较 System.out.println(numA == numC) ; // 对象比较 System.out.println(numA == numD) ; // 对象比较 } } //程序执行结果:true // true // false(使用了关键字new实例化了Integer类对象)
此时利用自动装箱的处理机制,定义了两个Integer类的对象,同时在使用“==”比较的时候也可以发现结果相同。
-
观察Integer比较超过127值时的情况:
public class Demo { public static void main(String args[]) { Integer numA = 128 ; Integer numB = 128 ; System.out.println(numA == numB) ; // 对象比较 System.out.println(numA.equals(numB)) ; // 对象比较 } } //程序执行结果:false // true
在使用Integer类进行相等判断的时候,“==”仅仅只能够针对于一位(byte)进行判断,所以一旦超过了127,就无法使用它来判断了,就必须使用equals()方法来完成最后的相等判断。
三、数据类型转换
使用包装类除了可以说让基本数据类型按照对象的形式处理之外,实际上还有一个最为重要的功能就是实现字符串与基本数据类型之间的转换处理,如果想完成这些转换,就需要使用到特定的处理方法,以下面三个为例:
- Integer类转换方法:public static int praseInt(String s);
- Double类转换方法:public static double praseDouble(String s);
- Boolean类转换方法:public static boolean praseBoolean(String s);
范例:将字符串转为基本数据类型
public class Demo {
public static void main(String args[]) {
int numA = Integer.parseInt("10") ; // 字符串转int
double numB = Double.parseDouble("39.9") ; // 字符串转double
boolean flag = Boolean.parseBoolean("true") ; // 字符串转boolean
System.out.println(numA * 2) ;
System.out.println(numB * 2) ;
System.out.println(flag == true) ;
}
}
//程序运行结果:20(字符串为10,转为整型后×2)
// 78.9(字符串为39.9,转为浮点型后×2)
// ture(字符串转为boolean)
但是在此类转换的时候需要注意一个问题:如果现在将一个字符串转为一个数字,那么一定要求保证该字符串全部由数字所组成,否则会出现异常。
范例:错误的数据转换
public class Demo {
public static void main(String args[]) {
String str = "1a3" ; // 字符串包含有非数字
int num = Integer.parseInt(str) ; // 错误
}
}
//此时编译时会出现:“java.lang.NumberFormatException”的错误提示
如果此时你的字符串组成有问题,那么最终执行转换的时候就会出现“NumberFormatException”异常信息,但是需要提醒的是,如果现在是将字符串转为boolean,那么是否为true或false没有特殊要求,如果不是这两个单词,同意按照false处理。
范例:观察字符串转boolean的操作
public class Demo {
public static void main(String args[]) {
String str = "1a3" ; // 字符串包含有非数字
boolean flag = Boolean.parseBoolean(str) ;
System.out.println(flag) ; // false
}
}
//程序执行结果:false
以上的这些转换处理是在实际项目开发过程中包装类最为核心的功能,但是这个时候就可以发现如下的一些关系:
-
如果要将字符串变为基本数据类型一般使用的是包装类的静态方法来完成;
-
如果将包装类变为字符串,有两种做法:
-
第一种做法(不可取):任意的基本数据类型使用“+”连接一个空字符串。
范例:将基本数据类型转为字符串
public class Demo { public static void main(String args[]) { double num = 100.93 ; // 基本数据类型 String str = num + "" ; // 基本数据类型转为字符串 System.out.println(str.length()) ; } } //程序执行结果:6
虽然这种转换可以成功,但是却存在有一个性能上的问题,因为要追加一个空字符串,所以就需要额外自动实例化一个空字符串的对象实例,而这个对象属于垃圾空间。
-
第二种方法(可取):在String类中提供有一系列的valueOf()方法,这些方法类似于基本数据类型的装箱操作,这些方法可以将基本数据类型变为字符串;
方法定义:public static String valueOf(数据类型 val);
范例:正确的基本数据类型转为字符串的操作
public class Demo { public static void main(String args[]) { double num = 100.93 ; // 基本数据类型 String str = String.valueOf(num) ; // 基本数据类型转String System.out.println(str.length()) ; } } //程序执行结果:6
-
在以后所有的开发之中,字符串转基本数据类型一定要用包装类,同时所有的项目都会存在有此类的功能,而如果要想将基本数据类型转为字符串,一定要用valueOf()方法完成,这样可以避免无用垃圾的生成。