包装类

来源:互联网 发布: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)
返回的是字符串

0 0
原创粉丝点击