夯实Java基础(六)——包装类
1、包装类简介
我们都知道java是面向对象编程语言,包含了8种基本数据类型,但是这8种基本数据类型并不支持面向对象的特征,它们既不是类,也不能调用方法。这在实际使用时存在很多的不便,比如int类型需要转换成字符串,为了解决这个不足。然后就出现了包装类,顾名思义,就是将这些基本数据类型封装在类中,并且提供丰富的方法来对数据进行操作。这样八个和基本数据类型对应的类统称为包装类(wrapper class)。
java中的包装类提供了将基本数据类型转换为对象,以及将对象转换为基本数据类型的机制。
其中byte,short,integer,float,double,long都属于number子类。character ,boolean属于object子类。它们的默认值都是null。
2、基本数据类型、包装类、字符串之间的转换
①、基本数据类型转换为包装类(装箱):调用包装类的构造器
//基本数据类型——>包装类:调用包装类的构造器 @test public void test1(){ int num=10; integer i1=new integer(num); system.out.println("i1结果:"+i1); integer i2=new integer("10"); system.out.println("i2结果:"+i2); //报错,必须是纯数字,java.lang.numberformatexception: for input string: "10abc" //integer i3=new integer("10abc"); //system.out.println(i3); double d1=new double(12.3); double d2=new double("12.3"); system.out.println("d1结果:"+d1); system.out.println("d1结果:"+d2); boolean b1=new boolean(true); boolean b2=new boolean("true"); boolean b3=new boolean("true123"); system.out.println("b1结果:"+b1); system.out.println("b2结果:"+b2); system.out.println("b3结果:"+b3); }
运行结果:
从运行的结果来看,通过调用包装类构造器可以将基本数据类型转为包装类,但是传入的参数必须合法,否则就像integer那样会报错。可以看见boolean包装类传入的字符串是忽略大写的,这是因为构造器中调用了parseboolean(string s)方法,然后这个方法内部又调用了string方法的equalsignorecase(string anotherstring)方法,所以传入字符串会忽略大小写。而且你传入的是非法字符串它并不会报错,只是返回了false,这里需要注意一下。
②、包装类转换为基本数据类型(拆箱):调用包装类的xxx的xxxvalue()方法
//包装类——>基本数据类型:调用包装类的xxx的xxxvalue()方法 @test public void test2(){ integer integer = new integer(10); int i=integer.intvalue(); system.out.println(i+1); double adouble = new double(10.11); double d=adouble.doublevalue(); system.out.println(d+1); boolean aboolean = new boolean(false); boolean b=aboolean.booleanvalue(); system.out.println(b); }
运行结果:
包装类转换为基本数据类型是非常简单的,只需要调用正确的方法即可,其他的包装类也是同样的道理。
你会发现前面两个点这样换来换去会非常的麻烦,其实从jdk5之后就变得非常简单了,这就要到后面介绍自动拆箱和自动装箱。
③、由于出现了自动拆箱和自动装箱,基本数据类型和包装类就可以看成一个整体。
基本数据类型、包装类转换为字符串:调用string重载的valueof(xxx xxx)
//基本数据类型、包装类->字符串:调用string重载的valueof(xxx xxx) @test public void test3(){ int num=10; //方式1:连接运算 string str1=num+""; system.out.println("str1结果"+str1); //方式2:调用string的valueof(xxx xx)方法 int num1=15; string str2=string.valueof(num1); system.out.println("str2结果"+str2); integer integer=new integer(21); string str3=string.valueof(integer); system.out.println("str3结果"+str3); }
运行结果:
④、字符串转换为基本数据类型、包装类:调用包装类中的parsexxx()方法
//字符串——>基本数据类型、包装类:调用包装类中的parsexxx()方法; @test public void test5(){ string str1="211"; int num=integer.parseint(str1); system.out.println(num); //运行报错,ava.lang.numberformatexception: for input string: "211abc" //string str2="211abc"; //int num1=integer.parseint(str2); string str3="truetrue"; boolean b=boolean.parseboolean(str3); system.out.println(b); }
运行结果:211、false。
无论怎样转换,数据的格式必须是正确的,否则就会报错,boolean特殊点,返回的是false。
最后它们三者的转换可以详细归结为:
1、基本数据类型与包装类之间转换:直接使用自动装箱和自动拆箱(后面会讲到,非常简单)。
2、基本数据类型、包装类转换为字符串:调用string的valueof(xxx xxx)方法。
3、字符串转换为基本数据类型、包装类:调用包装类的parsexxx()方法。
另外包装类中还有丰富的方法可供大家调用,如需学习可以自行查看包装类的api。
3、自动拆箱和自动装箱
将基本数据类型变成包装类称为装箱,将包装类的类型变为基本数据类型称为拆箱。
在jdk1.5之后,java提供了自动装箱和自动拆箱功能。
下面来看一下案例:
@test public void test6(){ int i=21; integer integer=i;//自动装箱 int j=integer;//自动拆箱 double d=21.11; double adouble=d; double e=adouble; }
由于出现了自动装箱和自动拆箱功能,所以基本数据类型和包装类之间的相互转换变得非常简单,再也不用去调用繁琐的方法了。
但是也会出现一些特殊的情况,案例如下:
@test public void test7(){ integer a=127; integer b=127; system.out.println(a == b); integer c=128; integer d=128; system.out.println(c == d); }
运行结果:
运行的结果肯定会有很大的疑问?同样是两个int型自动装箱为包装类进行比较,为什么127比较返回是true,而128比较则返回了false。这是为什么呢?这与java的integer类的设计有关,查看integer类的源代码,如下所示。
private static class integercache { static final int low = -128; static final int high; static final integer cache[]; static { // high value may be configured by property int h = 127; string integercachehighpropvalue = sun.misc.vm.getsavedproperty("java.lang.integer.integercache.high"); if (integercachehighpropvalue != null) { try { int i = parseint(integercachehighpropvalue); i = math.max(i, 127); // maximum array size is integer.max_value h = math.min(i, integer.max_value - (-low) -1); } catch( numberformatexception nfe) { // if the property cannot be parsed into an int, ignore it. } } //将127赋给high变量 high = h; //定义长度为256的integer数组 cache = new integer[(high - low) + 1]; int j = low; //执行初始化,创建-128~127的integer实例,并放入cache[]数组中 for(int k = 0; k < cache.length; k++) cache[k] = new integer(j++); // range [-128, 127] must be interned (jls7 5.1.7) assert integercache.high >= 127; } private integercache() {} }
从上面代码可以看出,integer类中定义了一个integercache内部类,内部类中定义了一个静态常量的integer cache [ ]数组,而这个数组存储了从-128~127之间的整数自动装箱成integer实例,如果我们使用自动装箱的方式,给integer包装类赋值时,范围在-128~127之间,就可以直接使用数组中的元素,因为-128~127之间的同一个整数自动装箱成integer实例时,永远是引用cache数组的同一个数组元素。如果超出了这个范围,自动装箱需要再重新new对象,所以就出现了程序中的运行结果。
4、小结
1、包装类的默认值都是null。
2、基本数据类型、包装类、字符串之间的转换可以归结为:
- 基本数据类型与包装类之间转换:直接使用自动装箱和自动拆箱。
- 基本数据类型、包装类转换为字符串:调用string的valueof(xxx xxx)方法。
- 字符串转换为基本数据类型、包装类:调用包装类的parsexxx()方法。
3、integer类中默认存放值的范围是-128~127之间。