1.
Java提供了两个类型系统,基本数据类型与引用数据类型。使用基本类型在于效率,然而当要使用只针对对象设计的API或新特性(例如多态性),怎么办呢?例如:
//情况1 equals(Object obj) 问题说明:因为Object类中的equals形参是引用数据类型的,当要调用这个方法的时候,任何一个引用数据类型的对象都可以放进来,要是想使用equals比较两个基本数据类型的话,基本数据类型就放不进来,因为引用数据类型和基本数据类型是两套体系 //情况2 ArrayList list = … list.add(Object obj) 问题说明:ArrayList就提供了一个add方法,在没有泛型的情况下,list对象调用add方法的形参就一个Object类型,意味着任何一个引用数据类型都可以放到这里,但是要是往里面添加如金额、成绩等基本数据类型就不可以
如上两种情况要想解决,把基本数据类型放进去就只能定义重载方法指明可以存放的具体类型,相当于每需要放入一个基本数据类型就要定义一个方法,这样就显的整个代码的设计比较臃肿和冗余,导致基本数据类型存入没法使用到类的多态性
为了使基本数据类型的数据具备类的特征,进而使用面向对象中丰富的特性(封装、继承、多态等)。此时,给每个基本数据类型提供了对应的包装类。(或封装类,Wrapper)
2.
封装以后的,内存结构对比:
public static void main(String[] args){ int num = 520; Integer obj = new Integer(520); }
2.1.通过自定义包装类说明包装类原理
如下所示:自定义一个MyInteger类包装int数据类型
创建一个MyInteger对象,里面只有一个int属性,,在造MyInteger对象的时候,因为对象里面有int value属性,假如value的属性值是12,那么MyInteger对象对应的数据值就是12。原来是针对于int数据进行存储,现在只需要提供一个MyInteger对象,对象的属性值是12就可以了。
因为MyInteger是一个类,就有了类的特性,比如继承、多态、调属性等,甚至可以在类中自定义一些方法,就使得基本数据类型的功能变得特别强大。
public class MyInteger { int value; public MyInteger() { } public MyInteger(int value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } }
3.3.基本数据类型与包装类之间的转换
3.1.为什么需要转换
场景一:比如:list.add(Object obj)的方法的参数只能接收对象,这时候需要将基本数据类型的变量转换为对象。
场景二:基本数据类型的变量转换为对象以后,此时对象不能进行+、-、*、/的操作,如果想具备这样的操作,就需要将对象转换为基本数据类型的变量。
3.2.装箱
装箱:把基本数据类型转为包装类对象
转为包装类的对象,是为了使用专门为对象设计的API和特性
基本数值—->包装对象:调用对应的包装类的构造器
int num = 10; Integer int1 = new Integer(10); System.out.println(int1.toString()); boolean b = false; Boolean aBoolean = new Boolean(b); System.out.println(aBoolean.toString()); float f1 = 12.3F; Float aFloat = new Float(f1); System.out.println(aFloat.toString()); String s1 = "12.3f"; Float aFloat1 = new Float(s1); System.out.println(aFloat1);
3.3.拆箱
拆箱:把包装类对象拆为基本数据类型
转为基本数据类型,一般是因为需要运算,Java中的大多数运算符是为基本数据类型设计的。比较、算术等
包装对象—->基本数值:调用包装类Xxx的xxxValue()方法
Integer int1 = new Integer(12); int i = int1.intValue(); System.out.println(i + 1); Double aDouble = new Double(12.3); double d = aDouble.doubleValue(); System.out.println(d);
3.4.自动装箱与拆箱(实际开发中使用)
由于我们经常要做基本类型与包装类之间的转换,从JDK5.0 (JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4); i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5; //加法运算完成后,再次装箱,把基本数值转成对象。
int num = 10; Integer int1 = num; //自动的装箱 boolean b1 = true; Boolean aBoolean = b1;//自动的装箱 float f1 = 12.3F; Float aFloat = f1;//自动的装箱 int i = int1; //自动的拆箱 int j = int1 + 10;//自动的拆箱 Integer int2 = int1 + 10;//拆箱、装箱
注意:只能与自己对应的类型之间才能实现自动装箱与拆箱。
Integer i = 1; Double d = 1;//错误的,1是int类型
4.
(1)基本数据类型转为字符串
方式1:
int a = 10; //String str = a;//错误的 String str = String.valueOf(a);
int a = 10; String str = a + "";
(2)字符串转为基本数据类型
方式1:除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型,例如:
public static int parseInt(String s)
:将字符串参数转换为对应的int基本类型。
public static long parseLong(String s)
:将字符串参数转换为对应的long基本类型。
public static double parseDouble(String s)
:将字符串参数转换为对应的double基本类型。
String s1 = "123"; int num1 = Integer.parseInt(s1); System.out.println(num1); //int num2 = (int)s1; //编译不通过 //s1 = "123a"; //int num2 = Integer.parseInt(s1);//报NumberFormatException异常 String s2 = "123.4"; double d1 = Double.parseDouble(s2); System.out.println(d1); float f1 = Float.parseFloat(s2); System.out.println(f1); String s3 = "true123"; boolean b = Boolean.parseBoolean(s3); System.out.println(b);
方式2:字符串转为包装类,然后可以自动拆箱为基本数据类型
public static Integer valueOf(String s)
:将字符串参数转换为对应的Integer包装类,然后可以自动拆箱为int基本类型
public static Long valueOf(String s)
:将字符串参数转换为对应的Long包装类,然后可以自动拆箱为long基本类型
public static Double valueOf(String s)
:将字符串参数转换为对应的Double包装类,然后可以自动拆箱为double基本类型
注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException
异常。
int a = Integer.parseInt("整数的字符串"); double d = Double.parseDouble("小数的字符串"); boolean b = Boolean.parseBoolean("true或false"); int a = Integer.valueOf("整数的字符串"); double d = Double.valueOf("小数的字符串"); boolean b = Boolean.valueOf("true或false"); int i = new Integer(“12”);
5.
6.6.包装类对象的特点
6.1.6.1 包装类缓存对象
包装类 | 缓存对象 |
---|---|
Byte | -128~127 |
Short | -128~127 |
Integer | -128~127 |
Long | -128~127 |
Float | 没有 |
Double | 没有 |
Character | 0~127 |
Boolean |
Integer a = 1; Integer b = 1; System.out.println(a == b);//true Integer i = 128; Integer j = 128; System.out.println(i == j);//false Integer m = new Integer(1);//新new的在堆中 Integer n = 1;//这个用的是缓冲的常量对象,在方法区 System.out.println(m == n);//false Integer x = new Integer(1);//新new的在堆中 Integer y = new Integer(1);//另一个新new的在堆中 System.out.println(x == y);//false
Double d1 = 1.0; Double d2 = 1.0; System.out.println(d1==d2);//false 比较地址,没有缓存对象,每一个都是新new的
6.2.
Integer i = 1000; double j = 1000; System.out.println(i==j);//true 会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
Integer i = 1000; int j = 1000; System.out.println(i==j);//true 会自动拆箱,按照基本数据类型进行比较
Integer i = 1; Double d = 1.0 System.out.println(i==d);//编译报错,两个对象之间不能用==进行比较
6.3.
public class TestExam { public static void main(String[] args) { int i = 1; Integer j = new Integer(2); Circle c = new Circle(); change(i,j,c); System.out.println("i = " + i);//1 System.out.println("j = " + j);//2 System.out.println("c.radius = " + c.radius);//10.0 } /* * 方法的参数传递机制: * (1)基本数据类型:形参的修改完全不影响实参 * (2)引用数据类型:通过形参修改对象的属性值,会影响实参的属性值 * 这类Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了 */ public static void change(int a ,Integer b,Circle c ){ a += 10; // b += 10;//等价于 b = new Integer(b+10); c.radius += 10; /*c = new Circle(); c.radius+=10;*/ } } class Circle{ double radius; }
转载请注明:西门飞冰的博客 » JAVA 包装类的使用