Java探秘之基本数据类型和包装类(int,Integer)

java有八种基本数据类型分别是,char、shoat、int、float、double、long、byte、boolean。

而它们对应的包装类也有,Character、Shoat、Integer、Float、Double、Long、Byte、Boolean。

那么他们之间有什么区别呢,简单来说他们是完全不同的概念,前者的java提供的基本数据类型,注意这里说了是基本数据类型;而后者则是java为它们提供常见处理的工具类,注意说了是类也就是它们存在着对象。

1.初始化

这里以int和Integer为例举例说明,当我们初始化一个int和一个Integer并没有给定他们值时,前者默认值为0,而后者默认为null(空对象)。

当我们需要传入一个参数时,对int、Integer的选择就很重要,如果我们传入的Intger为null很有可能抛出一个空指针异常使我们的程序蹦掉;而选择int时因为有初始值,不会出现Intger出现的问题,但是另一个问题也接踵而来,

我们不知道传入的int值的多少,很有可能就会给我们的程序埋了一个隐藏的bug;对于int还是Integer的选择我们应该通过现实场景进行选择。

这里重点说一下,当我们使用MVC模式开发时,Controller接收参数如果参数不存在,而参数是int类型时就会抛出一个参数不存在异常,而Integer却不会,只是得到的参数为null。

2)自动拆箱,自动装箱机制

自动拆箱和自动装箱机制是在JDK1.5引进的一个新机制,观察下面的代码,为什么会有这样的结果产生呢。

Integer a = 34;

int b = 34;

Integer c = b;

int d = a;

System.out.println( a == b);

System.out.println( d == c);

基本数据类型的和其包装类的相互转换,这是为什么呢?

答案很简单,因为我们在执行Integer a = 34; 代码时jdk默认执行的是Integer a = Integer.valueOf(34);

而我们在执行int d = a;时编译执行的却是int d = a.intValue();

你可能会有疑问,为什么会是这样?

这个时候我们就需要打开源码进行查看寻找答案。

/**

Returns an {@code Integer} instance representing the specified

{@code int} value. If a new {@code Integer} instance is not

required, this method should generally be used in preference to

the constructor {@link #Integer(int)}, as this method is likely

to yield significantly better space and time performance by

caching frequently requested values.

This method will always cache values in the range -128 to 127,

inclusive, and may cache other values outside of this range.

@param i an {@code int} value.

@return an {@code Integer} instance representing {@code i}.

@since 1.5

/

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

文档是这样说的,返回一个制定int数值的Integer对象实例,这样好像还不足以说明什么,那我们要如何证明我们是对的呢?

我们可以查看他的编译文件,一切就真相大白了(javac命令)。

public static void main(String[] var0) {

new User();

Integer var2 = Integer.valueOf(34);

byte var3 = 34;

Integer var4 = Integer.valueOf(var3);

int var5 = var2.intValue();

System.out.println(var2.intValue() == var3);

System.out.println(var5 == var4.intValue());

}

这好像就不需要我再多说什么了。

细心的小伙伴会看到文档里面有这么一句话 This method will always cache values in the range -128 to 127,inclusive, and may cache other values outside of this range.该方法会缓存-128到127之间的值,这句话又是什么意思呢。

Integer a = 120;Integer b = 120;Integer c = 300;Integer d = 300;System.out.println( a == b);System.out.println( d == c);这两句代码会输出什么呢,小伙伴们肯定说都是true啊,或者说都是false。会这样说的小伙伴不能说你错了,只能说你对了一半;是这样的啊,我们知道==运算符进行运算时,运算符两边如果都为基本数据类型的话那就直接对数值进行比较;但是如果两边或者一边为非基本数据类型时,即对象实例,则比较的是他们的内存地址(如果为空对象的话则为null),这里很明显两边都是对象实例,所以比较的是内存地址。

额?为什么是这样呢,按我们之前讲得理论不是应该都为false才对嘛,因为他们比较的是内存地址呀。哈哈,这就是我们之前讲到的问题,Integer会缓存-128到127之间的数值,而这么数值当然是缓存在一个对象实例里面啦,当我们需要使用时又进行取出(准确点来说是拿到的是它的引用),而不在这个范围内的数值当然都是重新创建实例啦,有兴趣的小伙伴可以进去看下源码。

3) 类型转换

这是包装类很大的存在原因,试想一下,我们有一个数值传递过来时是String或者说是Object类型,我们要怎么转换成int类型呢?

Integer的ValueOf可以将一个String类型转换成int。

使用强制类型转换编译器会报类型转换异常(String类型无法转换成Integert类型),使用valueof方法则可以通过编译,运行结果也是正确的;那么在试想一下,如果是 String a = "120.0";那会是怎么样的结果呢。

抛出一个异常,不能输入字符串为“120.0”,a是浮点类型的,那怎么办,总会有解决方法的。

哎呦,好像行不通,Float精度比Integer高,嗯!强转?

也不行,好像很绝望。Integer b = Float.valueOf(a).intValue();好像行了,测试一下。还真行,什么情况,这个intValue又是个什么方法。/**

Returns the value of this {@code Float} as an {@code int} after

a narrowing primitive conversion.

@return the {@code float} value represented by this object

converted to type {@code int}

@jls 5.1.3 Narrowing Primitive Conversions

*/

public int intValue() {

return (int)value;

}

什么,居然是个强转,搞了半天还是强转,那为啥我们那样转不行呢,因为我们是类强转,而它是类型转换。

挖槽还真可以,说明这就没错了。

4)内存使用

这次那long类型来举例,因为这样举例会比较明显,我们知道long类型是占8个字节(占用跟系统有关),而Long包装类呢,却是一个对象。

Long start = System.currentTimeMillis();

Long l = 0L;

for (Integer i = 0; i < Integer.MAX_VALUE; i++){

l++;

}

System.out.println(System.currentTimeMillis() - start);

这段代码会执行多久呢,好像是一瞬间的事,可是他执行了13060ms,可能这关系到机器,但是这个问题是很严重的,如果不小心写了这样的代码,搞蹦一个程序是很简单的事情。

这里每次执行l++操作其实都相当于创建了一个新的实例,那这个量就非常大了,而如果换成基本数据类型的话,从始至终它都是8个字节。

我们修改一下程序

Long start = System.currentTimeMillis();

long l = 0L;

for (int i = 0; i < Integer.MAX_VALUE; i++){

l++;

}

System.out.println(System.currentTimeMillis() - start);

那么它的运行时间又是多少呢?78ms

是不是很惊讶,相差了好几百倍,所以我们绝对不可以出现这样的代码,对于基本数据类型还是包装类的选择,我们首选还是基本数据类型,而当某些场景无法继续使用基本数据类型时,我们才使用包装类进行处理。

OK,到此为止,基本数据类型跟包装类之间的关系和区别我就讲完了,如果有讲的不好或者是讲得不对的地方大家一定要指出来,不然我就没法进步了!

 都看到这里了点个赞再走呗。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容