内容简介:JavaSE基础:包装类
Java在设计之初有一个基本原则:一切皆对象,一切的操作都要求用对象的形式进行描述。但是这里面就会出现一个矛盾, 基本数据类型不是对象 。那么我们会如何修复这个BUG呢?最简单的做法是将基本数据类型作为一个类的属性保存起来,这样就相当于把基本数据类型包装了一下.
实现基本数据类型的包装类
package com.shxt.demo01; public class Int {//类 private int number;//基本数据类型 public Int(int number){//提供一个参数的构造函数,传入基本数据类型 this.number = number; } public int intValue(){//取得包装类中的数据 return this.number; } //还可以提供其他的方法 }
package com.shxt.demo01; public class MyTest { public static void main(String[] args) { Int temp = new Int(100); //将基本数据类型包装后变为类 int result = temp.intValue(); //从类中取得基本数据类型 System.out.println(result+result); } }
代码分析:
我们实现了基本数据类型转成 Java 对象的方式,Java中给我们提供了类似的实现类
包装类表格
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
我们观察上述的表格发现除了int->Integer,char->Character,其他的都是基本数据类型的首字母大写,很好记忆的.
但是以上给出的包装类又分为两种子类型:
- 对象型包装类(Object直接子类):Character、Boolean。
- 数值型包装类(Number直接子类):Byte、Short、Integer、Float、Double、Long。
Number是一个抽象类,里面一共定义了六个操作方法:intValue()、shortValue()、byteValue()、floatValue()、longValue()、doubleValue()。
2.装箱和拆箱
现在已经存在有基本数据类型与包装类,那么这两种变量间的转换就通过以下方式定义。
-
装箱操作:将基本数据类型变为包装类的形式。
- 每个包装类的构造方法都可以接收各自数据类型的变量。
-
拆箱操作:从包装类之中取出被包装的数据。
- 利用Number类中提供的一系列的:xxxValue()方法完成。
示例1-以int和Integer为例演示装箱和拆箱操作的过程
public class Demo01 { public static void main(String args[]) { Integer obj = new Integer(10); // 将基本数据类型装箱 int temp = obj.intValue(); // 将基本数据类型拆箱 System.out.println(temp * 2); // 结果为20 } }
之前使用所编写的Int类,现在换成了Integer这个系统类。
示例2-以double和Double为例演示装箱和拆箱操作的过程
public class Demo02 { public static void main(String args[]) { Double obj = new Double(10.2); // 将基本数据类型装箱 double temp = obj.double Value(); // 将基本数据类型拆箱 System.out.println(temp * 2); // 结果为20.4 } }
示例3-以boolean和Boolean为例演示装箱和拆箱操作的过程(不是Number子类)
public class Demo03 { public static void main(String args[]) { Boolean obj = new Boolean(false); // 将基本数据类型装箱 boolean temp = obj.booleanValue(); // 将基本数据类型拆箱 System.out.println(temp); // 结果为false } }
现在可以发现,所有的包装类都使用了同样形式的方法进行操作。 在JDK1.5之前能够使用的操作都是以上形式的代码,但是JDK1.5之后,Java为了方便开发提供了 自动装箱 与 自动拆箱 的机制,并且可以直接利用包装类的对象进行数学计算。
示例4-以int和Integer为例观察自动装箱和自动拆箱操作的过程
public class Demo04 { public static void main(String args[]) { Integer obj = 10; // 自动装箱 int->Integer int temp = obj; // 自动拆箱 Integer->int 实际上调用了obj.intValue()方法 obj ++; System.out.println(temp * obj); // 结果为110 } }
示例5-以boolean和Boolean为例观察自动装箱和自动拆箱操作的过程(不是Number子类)
public class Demo05 { public static void main(String args[]) { Boolean obj = false; // 自动装箱 boolean->Boolean boolean flag = obj; // 自动拆箱 Boolean->boolean if(!flag){ System.out.println("Boolean不是Number的子类"); } } }
重点:正式因为Java提供了自动装箱和自动拆箱的机制,那么Object可以接收一切的数据类型(Object可以统一天下了)
转换流程:基本数据类型 → 自动装箱(成为对象) → 向上转型为Object。
示例6-以Object接收int数据类型演示转换过程
public class Demo06 { public static void main(String args[]) { Object obj = 10; // int->Integer(自动装箱为对象)->Object int temp = (Integer)obj; // Object->Integer(强制类型转换为包装类)->自动拆箱 obj ++; System.out.println(temp * obj); // 结果为110 } }
“莫名其妙”的NullPointException
在我们开发过程中,碰到过不少因为请求参数或者接口定义字段设置为int(或者其他基本类型)而导致NullPointException(空指针异常)。代码大致地运行步骤如下所示,当然不会跟这个完全一样。
public class Demo06 { public static void main(String args[]) { Integer a = null; int b = a; // 抛出NullPointException a.intValue(); } }
代码分析:
上面的代码可以编译通过,但是会抛出空指针异常(NullPointException)。
前面已经说过了, int b = a
实际上是 int b = a.intValue()
,
由于a的引用值为null,在空对象上调用方法就会抛出NullPointException。
3.==和equlas()
大家都应该清楚明了的了解两者的区别,
一句话说就是 ==
比较的是内存中地址, equlas()
对比的为数值,因为基本类型相同的数值指向的同一块内存,所以可以用==来比较,而引用类型则不可以。
public class Demo07 { public static void main(String args[]) { Integer obja = 10; // 直接赋值 Integer objb = 10; // 直接赋值 Integer objc = new Integer(10); // 构造方法 System.out.println(obja == objb); // true 不是比较内存地址吗?为什么? System.out.println(obja == objc); // false System.out.println(objb == objc); // false System.out.println(obja.equals(objc)); // true } }
代码分析:
obja == objb
不是应该比较内存地址吗?为什么能相等呢?我们需要解决这个问题,源码分析
在使用包装类的时候很少会利用构造方法完成,几乎都是直接赋值(这一点与String相同),但是在内容是否相等的时候,请一定要记住使用equals()方法。
两个包装类引用相等性
在Java中,“==”符号判断的内存地址所对应的值得相等性,具体来说,基本类型判断值是否相等,引用类型判断其指向的地址是否相等。看看下面的代码,两种类似的代码逻辑,但是得到截然不用的结果。
public class Demo08 { public static void main(String args[]) { Integer a1 = 127; Integer a2 = 127; System.out.println(a1 == a2); // true Integer b1 = 128; Integer b2 = 128; System.out.println(b1 == b2); // false } }
这个必须从源代码中才能找到答案。 Integer
类中的 valueOf()
方法的源代码如下:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) // 判断实参是否在可缓存范围内,默认为[-128, 127] return IntegerCache.cache[i + (-IntegerCache.low)]; // 如果在,则取出初始化的Integer对象 return new Integer(i); // 如果不在,则创建一个新的Integer对象 }
代码分析:
由于127属于[-128, 127]集合范围内,所以valueOf()每次都会取出同一个Integer对象,故第一个“==”判断结果为true;而128不属于[-128, 127]集合范围内,所以valueOf()每次都会创建一个新的Integer对象,由于两个新创建的对象的地址不一样,故第一个“==”判断结果为false。
再次分析比较过程
package com.shxt.demo01; public class MyTest { 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); // 缓存机制,返回值true System.out.println(e==f); // 超出了缓存机制, 返回值false // (a+b) 计算了自动拆箱变成了int类型, c比较需要自动拆箱变成int , 返回值true System.out.println(c==(a+b)); //(a+b) 计算了自动拆箱变成了int类型,因为使用equals比较内容(a+b)的结果有自动装箱,返回值true System.out.println(c.equals(a+b)); // (a+b) 计算了自动拆箱变成了int类型, g自动拆箱变成long类型, (a+b)的结果自动类型转换为long , 返回值true System.out.println(g==(a+b)); //(a+b) 计算了自动拆箱变成了int类型,因为使用equals比较内容(a+b)的结果有自动装箱Integer //Long和Integer比较 , 返回值false System.out.println(g.equals(a+b)); //涉及到自动类型转换, 返回值true System.out.println(g.equals(a+h)); } }
4.数据类型转换(核心)
使用包装类最多的情况实际上是它的数据类型转换功能上,在包装类里面,最大的优点就是提供将String型数据变为基本数据类型的方法,使用几个代表的类做说明:
- Integer类:public static int parseInt(String s)。
- Double 类:public static double parseDouble(String s)。
- Boolean类:public static boolean parseBoolean(String s)。
**特别注意:**Character类里面并不存在字符串变为字符的方法,因为String类有一个charAt()的方法可以根据索引取出字符内容,并且一个字符的长度才有一位。
范例1:将字符串变为int型数据
public class Demo01 { public static void main(String args[]) { String str = "123"; // 字符串 int temp = Integer.parseInt(str);//String->int System.out.println(temp * 2); } }
此时实现了字符串变为基本数据类型的操作。但是在这样的转换过程之中请一定要注意:被转换为数字的字符串一定要由数字所组成。如果不是数字组成,转换过程中会报异常:NumberFormatException
范例2:错误代码
public class Demo02 { public static void main(String args[]) { String str = "1sss3"; // 字符串 int temp = Integer.parseInt(str); System.out.println(temp * 2); } }
Exception in thread "main" java.lang.NumberFormatException:For input string:"1sss3"
范例3:将字符串变为double型数据
public class Demo03 { public static void main(String args[]) { String str = "13"; // 字符串 double temp = Double.parseDouble(str); System.out.println(temp * 2); //输出结果 26.0 } }
范例4:将字符串变为boolean型数据
public class Demo04 { public static void main(String args[]) { String str = "true"; // 字符串 boolean flag = Boolean.parseBoolean(str); if(flag) { System.out.println("满足条件!"); } else { System.out.println("不满足条件!"); } } } //控制台输出: 条件满足
范例5:将字符串变为boolean型数据
public class Demo05 { public static void main(String args[]) { String str = "hanpang"; // 错误字符串 boolean flag = Boolean.parseBoolean(str); if(flag) { System.out.println("满足条件!"); } else { System.out.println("不满足条件!"); } } } //控制台输出: 不满足条件!
代码分析:
在Boolean进行转换的过程里面,如果要转换的字符串不是true或者是false,那么将统一按照false进行处理。
现在既然实现了字符串变为基本数据类型操作,那么也一定可以实现基本数据类型变为字符串的操作,对于此类操作有两种做法:
-
操作一:任何基本数据类型与字符串使用了“+”操作之后都表示变为字符串。
public class Demo06 { public static void main(String args[]) { int num = 100; String str = num + ""; // 变为String System.out.println(str.replaceAll("0", "9")); } } //控制台输出: 199
这样的操作虽然可以简单的完成,但是会存在有垃圾的问题。
-
操作二:public static String valueOf(数据类型 变量) 开发推荐
public class Demo07 { public static void main(String args[]) { int num = 100; String str = String.valueOf(num); // 变为String System.out.println(str.replaceAll("0", "9")); } }
这样的转换不会产生垃圾,所以在开发时往往会使用以上做法。
5.小结
- 一定要清楚JDK1.5之后才提供有自动装箱与拆箱操作。
-
字符串与基本数据类型的互相转换:
- 字符串变为基本数据类型,依靠包装类的parseXxx()方法。
- 基本数据类型变为字符串,依靠String.valueOf(数据类型 变量)方法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 一分钟理解 Java 包装类型
- 包装常见的python命名空间
- css – 浮动流体图像留下文本包装
- 14.java 基本数据类型的包装类
- 前端开发如何包装可重用的JavaScript代码
- html – 如果需要,我如何允许文字包装一个字?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。