基本数据类型的装箱和拆箱()优先使用基本数据类型
2017-02-25 22:18
225 查看
包装类型是一个类,它提供了诸如构造方法、类型转换、比较等非常实用的功能,而且在Java 5之后又实现了与基本类型之间的自动转换,这使包装类型如虎添翼,更是应用广泛了,在开发中包装类型已经随处可见,但无论是从安全性、性能方面来说,还是从稳定性方面来说,基本类型都是首选方案。我们来看一段代码:
public class Client {
public static void main(String[] args) {
Client cilent = new Client();
int i=140;
//分别传递int类型和Integer类型
cilent.f(i);
cilent.f(Integer.valueOf(i));
}
public void f(long a) {
System.out.println("基本类型的方法被调用");
}
public void f(Long a) {
System.out.println("包装类型的方法被调用");
}
}
在上面的程序中首先声明了一个int变量i,然后加宽转变成long型,再调用f()方法,分别传递int和long的基本类型和包装类型,诸位想想该程序是否能够编译?如果能编译输出结果又是什么呢?
首先,这段程序绝对是能够编译的。不过,说不能编译的同学还是很动了一番脑筋的,只是还欠缺点火候,你可能会猜测以下这些地方不能编译:
f()方法重载有问题。定义的两个f()方法实现了重载,一个形参是基本类型,一个形参是包装类型,这类重载很正常。虽然基本类型和包装类型有自动装箱、自动拆箱的功能,但并不影响它们的重载,自动拆箱(装箱)只有在赋值时才会发生,和重载没有关系。
cilent.f(i)报错。i是int类型,传递到fun(long l)是没有任何问题的,编译器会自动把i的类型加宽,并将其转变为long型,这是基本类型的转换规则,也没有任何问题。
cilent.f(Integer.valueOf(i)) 报错。代码中没有f(Integer i)方法,不可能接收一个Integer类型的参数,而且Integer和Long两个包装类型是兄弟关系,不是继承关系,那就是说肯定编译失败了?不,编译是成功的,稍后再解释为什么这里编译成功。
既然编译通过了,我们来看一下输出:
基本类型的方法被调用
基本类型的方法被调用
cilent.f(i)的输出是正常的,我们已经解释过了。那第二个输出就让人很困惑了,为什么会调用f(long a)方法呢?这是因为自动装箱有一个重要的原则:基本类型可以先加宽,再转变成宽类型的包装类型,但不能直接转变成宽类型的包装类型。这句话比较拗口,简单地说就是, int可以加宽转变成long,然后再转变成Long对象,但不能直接转变成包装类型,注意这里指的都是自动转换,不是通过构造函数生成。为了解释这个原则,我们再来看一个例子:
public class Client {
public static void main(String[] args) {
int i=100;
f(i);
}
public static void f(Long l){
}
}
这段程序编译是通不过的,因为i是一个int类型,不能自动转变为Long型。但是修改成以下代码就可以编译通过了:
public static void main(String[] args) {
int i=100;
long l = (long)i;
f(l);
}
这就是int先加宽转变为long型,然后自动转换成Long型。规则说明白了,我们继续来看f(Integer.valueOf(i))是如何调用的,Integer.valueOf(i)返回的是一个Integer对象,这没错,但是Integer和int是可以互相转换的。没有f(Integer i)方法?没关系,编译器会尝试转换成int类型的实参调用,OK,这次成功了,与f(i)相同了,于是乎被加宽转变成long型—结果也很明显了。整个f(Integer.valueOf(i))的执行过程是这样的:
i通过valueOf方法包装成一个Integer对象。
由于没有f(Integer i)方法,编译器“聪明”地把Integer对象转换成int。
int自动拓宽为long,编译结束。
使用包装类型确实有方便的地方,但是也会引起一些不必要的困惑,比如我们这个例子,如果f()的两个重载方法使用的是基本类型,而且实参也是基本类型,就不会产生以上问题,而且程序的可读性更强。自动装箱(拆箱)虽然很方便,但引起的问题也非常严重—我们甚至都不知道执行的是哪个方法。
public class Client {
public static void main(String[] args) {
Client cilent = new Client();
int i=140;
//分别传递int类型和Integer类型
cilent.f(i);
cilent.f(Integer.valueOf(i));
}
public void f(long a) {
System.out.println("基本类型的方法被调用");
}
public void f(Long a) {
System.out.println("包装类型的方法被调用");
}
}
在上面的程序中首先声明了一个int变量i,然后加宽转变成long型,再调用f()方法,分别传递int和long的基本类型和包装类型,诸位想想该程序是否能够编译?如果能编译输出结果又是什么呢?
首先,这段程序绝对是能够编译的。不过,说不能编译的同学还是很动了一番脑筋的,只是还欠缺点火候,你可能会猜测以下这些地方不能编译:
f()方法重载有问题。定义的两个f()方法实现了重载,一个形参是基本类型,一个形参是包装类型,这类重载很正常。虽然基本类型和包装类型有自动装箱、自动拆箱的功能,但并不影响它们的重载,自动拆箱(装箱)只有在赋值时才会发生,和重载没有关系。
cilent.f(i)报错。i是int类型,传递到fun(long l)是没有任何问题的,编译器会自动把i的类型加宽,并将其转变为long型,这是基本类型的转换规则,也没有任何问题。
cilent.f(Integer.valueOf(i)) 报错。代码中没有f(Integer i)方法,不可能接收一个Integer类型的参数,而且Integer和Long两个包装类型是兄弟关系,不是继承关系,那就是说肯定编译失败了?不,编译是成功的,稍后再解释为什么这里编译成功。
既然编译通过了,我们来看一下输出:
基本类型的方法被调用
基本类型的方法被调用
cilent.f(i)的输出是正常的,我们已经解释过了。那第二个输出就让人很困惑了,为什么会调用f(long a)方法呢?这是因为自动装箱有一个重要的原则:基本类型可以先加宽,再转变成宽类型的包装类型,但不能直接转变成宽类型的包装类型。这句话比较拗口,简单地说就是, int可以加宽转变成long,然后再转变成Long对象,但不能直接转变成包装类型,注意这里指的都是自动转换,不是通过构造函数生成。为了解释这个原则,我们再来看一个例子:
public class Client {
public static void main(String[] args) {
int i=100;
f(i);
}
public static void f(Long l){
}
}
这段程序编译是通不过的,因为i是一个int类型,不能自动转变为Long型。但是修改成以下代码就可以编译通过了:
public static void main(String[] args) {
int i=100;
long l = (long)i;
f(l);
}
这就是int先加宽转变为long型,然后自动转换成Long型。规则说明白了,我们继续来看f(Integer.valueOf(i))是如何调用的,Integer.valueOf(i)返回的是一个Integer对象,这没错,但是Integer和int是可以互相转换的。没有f(Integer i)方法?没关系,编译器会尝试转换成int类型的实参调用,OK,这次成功了,与f(i)相同了,于是乎被加宽转变成long型—结果也很明显了。整个f(Integer.valueOf(i))的执行过程是这样的:
i通过valueOf方法包装成一个Integer对象。
由于没有f(Integer i)方法,编译器“聪明”地把Integer对象转换成int。
int自动拓宽为long,编译结束。
使用包装类型确实有方便的地方,但是也会引起一些不必要的困惑,比如我们这个例子,如果f()的两个重载方法使用的是基本类型,而且实参也是基本类型,就不会产生以上问题,而且程序的可读性更强。自动装箱(拆箱)虽然很方便,但引起的问题也非常严重—我们甚至都不知道执行的是哪个方法。
相关文章推荐
- 黑马程序员_高新技术:1)eclipse的使用技巧_可变参数_增强for循环_基本数据类型的自动拆箱与装箱
- 加强eclipse的使用技巧。可变参数。基本数据类型自动装箱和拆箱。枚举。反射。数组反射的应用。ArrayList和HashSet。JavaBean
- 黑马程序员_高新技术_eclipse的使用技巧_可变参数_增强for循环_基本数据类型的自动拆箱与装箱
- 静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱
- Java中基本数据类型的自动拆箱和装箱
- 【JAVA学习】java基本数据类型与字符串之间的转换(基本数据类型、对象封装类、自动装箱、自动拆箱)
- Java深入(高新技术)(二):开发环境、静态导入、可变参数、增强for循环、基本数据类型的自动拆箱与装箱、享元模式
- 基本数据类型的自动拆箱与装箱
- Eclipes使用,可变参数,高级For循环,基本数据自动装箱拆箱
- 黑马程序员__ 基本数据类型的自动拆箱和装箱
- 基本数据类型对象包装类、自动装箱和自动拆箱
- 黑马程序员--张孝祥Java高新技术-JDK1.5新特性(二)【基本数据类型的自动拆箱与装箱,枚举】以及享元设计模式
- Java高新技术【1】 (静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱)
- 黑马程序员-------(高新技术)静态导入、可变参数、增强for循环、基本数据类型的自动拆箱与装箱
- Java中基本数据类型的自动拆箱和装箱
- java基本数据类型与字符串之间的转换(基本数据类型、对象封装类、自动装箱、自动拆箱)
- JAVA1.5新特性----基本数据类型的自动拆箱与装箱
- Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法?
- 基本数据类型对象包装类和自动装箱自动拆箱技术
- Java高新技术【1】 (静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱)