首页 > 代码库 > java从基础知识(一)数据类型(下)
java从基础知识(一)数据类型(下)
前面介绍了java的8种基本数据类型,包括boolean, byte, char, short, int, long, float, double。同时,java也提供了这些类型的封装类,分别为Boolean, Byte, Character, Short, Integer, Long, Float, Double。这些封装类被放在了java.lang包下。
1、为什么需要基本类型的封装类?
通过查看资料及个人分析,封装类与基本类型的区别及优势主要可归结为以下4点:
1)int是面向机器底层的数值类型,是Primitive类型的数据类型,一般只用在数值计算中,而Integer是int的Warpper类,是面向对象的即OOP的对象类型,是用在Java的其它要使用对象的地方,比如Map的Key与Value,List与Set的Element若要保存数值信息都要把int包装成Integer对象使用。int 一般做为数值参数就够了,integer 一般做类型转换的时候用的较多。
2)基本数据类型都有默认值,无法表达空的情况。Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
3)int 是基本类型,Integer是引用类型。封装类需要涉及到对象的实例化和回收,效率相比基本数据类型要低。封装类实现了很多对基本数据类型的操作的工具方法及整数的最大值最小值常量等,易用性要比基本数据类型要好。
4)存储位置不同,封装类的对象的引用放在栈里面,对象的实例放在堆里面。而基本数据类型是成员变量的时候放在堆里面,是局部变量的时候放在栈里面(方法栈)。
2、java的自动装箱、拆箱
从Java 5开始,引入了自动装箱/拆箱机制,使得基本数据类型和其封装类间实现方便快捷的转换
装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。
如:Integer a = 100; //这是自动装箱 (编译器调用的是static Integer的valueOf(int i)方法)
拆箱:和装箱相反,将引用类型的对象简化成值类型的数据
如:int b = new Integer(100); //这是自动拆箱(编译器调用的是Integer intValue()方法)
装箱机制存在一个小陷阱需要注意一下
public static void main(String arg[]){ Integer i1 = 123; Integer i2 = 123; System.out.println("i1 equal i2 : " + (i1.equals(i2))); System.out.println("i1 == i2 : " + (i1 == i2)); }
在执行上述代码之后,我们会发现以下神奇结果:
i1 equal i2 : true i1 == i2 : true
查看源码很快发现问题所在,源码如下(其中low=-128,high=127)
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
原来是java在自动装箱时将值在-128~127之间的数值放在了cache中,通过自动装箱的引用都指向这个固定的cache地址,而不是分配新的存储空间(这种现象在Byte、Short、Integer、Long、Character这些封装类中均是这样,有兴趣的看看源码就可知道)。
相信小伙伴们在看了上面的代码之后都开始怀疑人生了,觉得自己之前对“==”和“equal”的理解是不是错了,接下来给出正常逻辑结果的代码
public static void main(String arg[]){ Integer i1 = 128; Integer i2 = 128; System.out.println("i1==i2 : " + (i1 == i2)); System.out.println("i1 equal i2 : " + i1.equals(i2)); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println("i3==i4 : " + (i3 == i4)); System.out.println("i3 equal i4 : " + i3.equals(i4)); }
运行结果
i1==i2 : false i1 equal i2 : true i3==i4 : false i3 equal i4 : true
哈哈,世界还是美好的,相信现在心情美丽多了。
从上面代码及运行结果可以看出,当自动装箱的值不在-128~127之间时,java虚拟机会为该对象分配新的存储空间,即new一个新的对象。
3、封装类的方法
1)构造方法:每个封装类都会提供一个带基本数据类型的构造方法
如Boolean(boolean value)、Byte(byte value)、Character(char value)等,用于将对应的基本数据类型手动分装。
2)拆装方法
如booleanValue()、byteValue()、charValue等,将引用类型转为对应的基本数据类型。
如parseFloat(String s)、parseByte(String s)等,将String类型转为对应的基本数据类型,parseFloat("3.14")转化为float类型。
3)封装方法(分为两类)
如valueOf(boolean value)、valueOf(byte value)、valueOf(char value)等,将对基本数据类型转换为对应的封装类。
如valueOf(String s) 将String类型转为对应的封装类型,Float.valueOf("3.14")会将字符串“3.14”转化为Float类型。
4)字符串化方法
如toString()、toString(Float value)等,将封装类型转化为Stirng类型。
5)比较方法
如compareTo()用于比较两个值大小,equals()比较两个值是否相等。
上面是基本数据类型封装类的一些公共方法,也是在日常工作中经常用到的方法。各个封装类还有自己独有的一些方法,有时间可以自己研究研究。
java从基础知识(一)数据类型(下)