包装类
来源:互联网 发布:c语言扩大数组最大大小 编辑:程序博客网 时间:2024/04/28 04:40
一.为什么需要包装类
java语言是一个面向对象的语言,但是java中的基本数据类型却不是面向对象的,但是我们在实际使用中经常需要将基本数据转换成对象,比如集合的操作.为了便于操作.这时,我们就需要将基本类型数据转换成对象,所以需要包装类
二.包装类位与java.lang包下,包装类和基本数据类型的对应关系
byte—Byte
boolean—Boolean
short—Short
char—Character
int—Integer
long—Long
float—Float
double—Double
void—Void(类中无任何东西,忽略)
三.包装类的作用
- 提供一种机制,将基本值“包装”到对象中,从而使基本值能够包含在为对象而保留的操作中,比如添加到Collections 中,或者从带对象返回值的方法中返回,还可以包含每种基本数据类型的相关属性,如最大值,最小值。
- 为基本值提供分类功能。这些功能大多数与各种转换有关:在基本值和String对象间相互转换,在基本值和String对象之间按不同基数转换,如二进制、八进制和十六进制。
四.装箱与拆箱
1.装箱:由基本类型向对应的包装类转换称为装箱
Integer I = new Integer(100); //手动装箱Integer I = 100;(JDK5之后才可以使用) //自动装箱,本质上是编译器编译时为我们做了手动装箱
2.拆箱:由包装类向对应的基本类型转换称为拆箱
int a = new Integer(100).intValue(); //手动拆箱int a = new Integer(100); //自动拆箱,本质上是编译器在编译时为我们做了手动拆箱
由以上代码可知:装箱过程是通过调用包装器的valueOf()方法实现的,而拆箱过程是通过调用包装器的xxxValue方法实现的。(xxx代表对应的基本数据类型)。
五.自动装箱的缓存机制,这里通过代码来解释
package com.zgzlive.wrappedtest;public class wrappedTest1 { public static void main(String[] args) { //Integer a = new Integer(1000); Integer a = 1000; //JDK5.0之后,自动装箱,编译器把这句改为:Integer a = new Integer(1000); int x = new Integer(2000); //自动拆箱,编译器把这句改为:int x = new Integer(2000).intValue(); Integer b = 2000; int c = b; //自动拆箱,编译器把这句改为:b.intValue(); Integer i = null; //int j = i.intValue(); //编译不会报错,但是运行时报错空指针异常 Integer d1 = 1234; Integer d2 = 1234; System.out.println(d1==d2); //输出结果为false System.out.println(d1.equals(d2)); //输出结果为true /* * 自动装箱的缓存机制 * 从Integer的valueOf()源码得知: * java为了提高效率,IntegerCache类中有一个数组缓存了值从-128到127的Integer对象。 * 当我们调用Integer.valueOf(int i)的时候,如果数值在 [-128,127] 之间, * 会直接从这个缓存数组中返回一个对象;否则会new一个新的Integer对象。 * 下面的代码中 d3 和 d4 的数值为100,因此会直接从cache中取已经存在的对象, * 所以 d3和 d4 指向的是同一个对象,而 d5 和 d6 则是分别指向不同的对象。 */ Integer d3 = 100; Integer d4 = 100; System.out.println(d3==d4); //输出结果为true System.out.println(d3.equals(d4)); //输出结果为true Integer d5 = 200; Integer d6 = 200; System.out.println(d5==d6); //输出结果为false System.out.println(d5.equals(d6)); //输出结果为true /* * 从Double的valueOf()源码得知: * Double的valueOf()的实现和上面Integer的不同 * 因为在某个范围内的整型数值的个数是有限的,而浮点数却不是。 */ Double e1 = 100.0; Double e2 = 100.0; Double e3 = 100.0; Double e4 = 100.0; System.out.println(e1==e2); //输出结果为false System.out.println(e3==e4); //输出结果为false /* * 通过上面两个例子,应该注意的是: * Integer、Short、Byte、Character、Long这几个类的valueOf方法都用到了缓存机制, * Double、Float、Boolean的valueOf方法则没有提供缓存机制。 */ }}
例1:下面代码的输出结果是什么
public class Test2 { public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L; System.out.println(c == d); System.out.println(e == f); System.out.println(c == (a + b)); System.out.println(c.equals(a + b)); System.out.println(g == (a + b)); System.out.println(g.equals(a + b)); System.out.println(g.equals(a + h)); }}
输出结果:
true
false
true
true
true
false
true
结果分析:
当 “==” 运算符的两个操作数都是包装器类型的引用,是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程).另外,对于包装器类型,equals方法并不会进行类型转换.
第一个和第二个输出结果没有什么疑问。
第三句由于 a+b 包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。
第四句由于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf()方法,再进行equals比较。
同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。
例2:(1)哪一行是拆箱?(2)根据while循环里的条件判断,循环可不可以运行?(3)把3、4行注释掉,去掉第5、6行的注释后,循环会运行吗?
public class TestWhile{ public static void main(String[] args){ Integer i=0;//3 Integer j=0;//4 // Integer i=new Integer(0);//5 // Integer j=new Integer(0);//6 while(i<=j & i>=j & i!=j) { System.out.println("0000"); } } }
结果分析:
(1)while进行了拆箱:
对于Integer类型,<,<=,>,>=操作将导致拆箱操作,也就是调用Integer的intValue()方法得到相应的基本类型值,然后比较。但是,==,!=比较的是对象的引用(Reference)。
(2)3,4行为条件,循环不可以运行:因为3,4行进行了自动装箱,也就是调用Integer.valueOf(int i);注意,不是使用new,由于0在-128~127之间,根据缓存机制,i和j引用的是同一个对象。根据循环条件i<=j & i>=j & i!=j中,i<=j和 i>=j都成立,而i!=j不成立,因为i和j引用的是同一个对象。故循环不会运行
(3)把3,4行注释掉,5,6行为条件,循环可以运行:因为使用new创建了新的对象,故i和j引用的不是同一个对象,所以i!=j成立。i<=j& i>=j & i!=j成立,循环条件总是成立的,while(i <= j & i >= j & i != j)成为无穷循环,不断输出。
六.基本数据类型和字符串间的相互转换
1.基本数据类型→字符串:
- 使用对应包装类的toString()方法:(new Integer(1)).toString();
- 使用String类的valueOf()方法:String.valueOf(1);
- 使用空字符串””加上基本数据类型:1+””;
2.字符串→基本数据类型:
- 使用要转换为的基本数据类型的包装类的parseXxx()方法:Integer.parseInt(“1”);
- 使用要转换为的基本数据类型的包装类的valueOf()方法:Integer.valueOf(“1”);
七.包装类的方法(大致概括,需要的话看API)
1.以基本值参数并创建包装类对象的构造函数。如利用Integer包装类创建对象,Integer obj=new Integer(145);
2.以字符串参数并创建包装类对象的构造函数.如:new Integer(String s);
3.可生成基本值的typeValue方法,如:obj.intValue();
4.将字符串转换为基本值的parseType方法,如:Integer.parseInt(String s);
5.生成哈稀表代码的hashCode方法,如:obj.hasCode();
6.对同一个类的两个对象进行比较的equals()方法,如:obj1.eauqls(obj2);
7.生成字符串表示法的toString()方法,如:obj.toString().
8.进制转换,把十进制转换为十六进制,八进制,二进制
toBinaryString(int i)
toHexString(int i)
toOctalString(int i)
返回的是字符串