目录

了解

理解自动装箱、拆箱

自动装箱 / 自动拆箱在编程实践中有什么需要注意的地方

源码分析

原始类型线程安全

Java 原始数据类型和引用类型局限性


了解

int 是我们常说的整形数字,是 Java 的 8 个原始数据类型(Primitive Types,boolean、byte 、short、char、int、float、double、long)之一。Java 语言虽然号称一切都是对象,但原始数据类型是例外。

Integer 是 int 对应的包装类,它有一个 int 类型的字段存储数据,并且提供了基本操作,比如数学运算、int 和字符串之间转换等。在 Java 5 中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java 可以根据上下文,自动进行转换。

关于 Integer 的值缓存,这涉及 Java 5 中另一个改进。构建 Integer 对象的传统方式是直接调用构造器,直接 new 一个对象。但是根据实践,我们发现大部分数据操作都是集中在有限的、较小的数值范围,因而,在 Java 5 中新增了静态工厂方法 valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照 Javadoc,这个值默认缓存是 -128 到 127 之间。

理解自动装箱、拆箱

自动装箱实际上算是一种语法糖。什么是语法糖?可以简单理解为 Java 平台为我们自动进行了一些转换,保证不同的写法在运行时等价,它们发生在编译阶段,也就是生成的字节码是一致的。

javac 替我们自动把装箱转换为 Integer.valueOf(),把拆箱替换为 Integer.intValue()

这种缓存机制并不是只有 Integer 才有,同样存在于其他的一些包装类,比如:

  • Boolean,缓存了 true/false 对应实例,确切说,只会返回两个常量实例 Boolean.TRUE/FALSE。

  • Short,同样是缓存了 -128 到 127 之间的数值。

  • Byte,数值有限,所以全部都被缓存。

  • Character,缓存范围’\u0000’ 到 ‘\u007F’。

自动装箱 / 自动拆箱在编程实践中有什么需要注意的地方

原则上,建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合,创建 10 万个 Java 对象和 10 万个整数的开销可不是一个数量级的,不管是内存使用还是处理速度,光是对象头的空间占用就已经是数量级的差距了。

我们其实可以把这个观点扩展开,使用原始数据类型、数组甚至本地代码实现等,在性能极度敏感的场景往往具有比较大的优势,用其替换掉包装类、动态数组(如 ArrayList)等可以作为性能优化的备选项。一些追求极致性能的产品或者类库,会极力避免创建过多对象。当然,在大多数产品代码里,并没有必要这么做,还是以开发效率优先。

源码分析

整体看一下 Integer 的职责,它主要包括各种基础的常量,比如最大值、最小值、位数等;前面提到的各种静态工厂方法 valueOf();获取环境变量数值的方法;各种转换方法,比如转换为不同进制的字符串,如 8 进制,或者反过来的解析方法等。

首先,继续深挖缓存,Integer 的缓存范围虽然默认是 -128 到 127,但是在特别的应用场景,比如我们明确知道应用会频繁使用更大的数值,这时候应该怎么办呢?

缓存上限值实际是可以根据需要调整的,JVM 提供了参数设置:

-XX:AutoBoxCacheMax=N

这些实现,都体现在java.lang.Integer源码之中,并实现在 IntegerCache 的静态初始化块里。

private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =VM.getSavedProperty("java.lang.Integer.IntegerCache.high");...// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}...}

第二,我们在分析字符串的设计实现时,提到过字符串是不可变的,保证了基本的信息安全和并发编程中的线程安全。如果你去看包装类里存储数值的成员变量“value”,你会发现,不管是 Integer 还 Boolean 等,都被声明为“private final”,所以,它们同样是不可变类型!

这种设计是可以理解的,或者说是必须的选择。想象一下这个应用场景,比如 Integer 提供了 getInteger() 方法,用于方便地读取系统属性,我们可以用属性来设置服务器某个服务的端口,如果我可以轻易地把获取到的 Integer 对象改变为其他数值,这会带来产品可靠性方面的严重问题。

第三,Integer 等包装类,定义了类似 SIZE 或者 BYTES 这样的常量,这反映了什么样的设计考虑呢?如果你使用过其他语言,比如 C、C++,类似整数的位数,其实是不确定的,可能在不同的平台,比如 32 位或者 64 位平台,存在非常大的不同。但是在java中,原始数据类型是不存在差异的,这些明确定义在Java 语言规范里面,不管是 32 位还是 64 位环境,开发者无需担心数据的位数差异。

原始类型线程安全

前面提到了线程安全设计,你有没有想过,原始数据类型操作是不是线程安全的呢?

这里可能存在着不同层面的问题:

  • 原始数据类型的变量,显然要使用并发相关手段,才能保证线程安全。如果有线程安全的计算需要,建议考虑使用类似 AtomicInteger、AtomicLong 这样的线程安全类。

  • 特别的是,部分比较宽的数据类型,比如 float、double,甚至不能保证更新操作的原子性,可能出现程序读取到只更新了一半数据位的数值!

Java 原始数据类型和引用类型局限性

  • 原始数据类型和 Java 泛型并不能配合使用

这是因为 Java 的泛型某种程度上可以算作伪泛型,它完全是一种编译期的技巧,Java 编译期会自动将类型转换为对应的特定类型,这就决定了使用泛型,必须保证相应类型可以转换为 Object。

  • 无法高效地表达数据,也不便于表达复杂的数据结构,比如 vector 和 tuple

我们知道 Java 的对象都是引用类型,如果是一个原始数据类型数组,它在内存里是一段连续的内存,而对象数组则不然,数据存储的是引用,对象往往是分散地存储在堆的不同位置。这种设计虽然带来了极大灵活性,但是也导致了数据操作的低效,尤其是无法充分利用现代 CPU 缓存机制。

Java 为对象内建了各种多态、线程安全等方面的支持,但这不是所有场合的需求,尤其是数据处理重要性日益提高,更加高密度的值类型是非常现实的需求。

int和Integer有什么区别(转)相关推荐

  1. 面试刷题7:int和Integer有什么区别?

    原始数据类型是java系统的重要组成元素.java号称一切都是对象,原始数据类型除外. 我是李福春,我在准备面试,今天我们来回答一个问题: int和Integer有什么区别? int是原始数据类型,并 ...

  2. 面试官:int和Integer有什么区别?为什么要有包装类?

    作者 | 磊哥 来源 | Java面试真题解析(ID:aimianshi666) 转载请联系授权(微信ID:GG_Stone) 重要说明:本篇为博主<面试题精选-基础篇>系列中的一篇,查看 ...

  3. int和Integer有什么区别?

    可参考:http://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html 从Java 5开始引入了自动装箱/拆箱机制,使得二者可 ...

  4. int 和 Integer 有什么区别

    Java 提供两种不同的类型:引用类型和原始类型(或内置类型). Int是java的原始数据类型, Integer是java为int提供的封装类. Java为每个原始类型提供了封装类. 原始类型封装类 ...

  5. Java经典面试题—— int 和 Integer 有什么区别?谈谈 Integer 的值缓存范围

    典型回答 int 是我们常说的整型数字,是 Java 的 8 个原始数据类型(PrimitiveTypes,boolean.char.byte.short.int.long.float 和 doubl ...

  6. int 和 Integer 有什么区别,Integer的值缓存范围

    目录 int与Integer的基本使用对比 int与Integer的深入对比 int与Integer的基本使用对比 Integer是int的包装类:int是基本数据类型: Integer变量必须实例化 ...

  7. int 和 Integer有什么区别,Integer 有哪些函数方法

    [基本数据类型对象包装类JDk1.5以后的新特性]--[自动拆箱,装箱] 简化书写. Integer i = new Integer(5); 基本数据类型对象包装类,对象创建的简化写法Integer ...

  8. 基础回顾(正则、循环、和、 int和Integer、String /StringBuffer、Array和ArrayList、值传递和引用传递、 Lamda、java8)

    1. 正则表达式 1.1 Java中是如何支持正则表达式操作的? Java中的String类提供了支持正则表达式操作的方法,包括:matches().replaceAll().replaceFirst ...

  9. Java int 和 Integer 互转原理

    文章目录 Java int 和 Integer 互转 Java Integer.int 与 new Integer() Integer.valueOf() new Integer() 为什么 Java ...

最新文章

  1. 调用bat文件执行java文件
  2. 疫情严重!国内互联网公司上班时间汇总!
  3. 计算机photoshop知识点,计算机一级Photoshop知识点
  4. Android中ICS4.0Launcher中Fold的功能详解【androidICS4.0--Launcher系列三】
  5. 说明 RISC 和 CISC 指令系统的区别?
  6. element中的table相关
  7. 代挂管家易开源7.4+web版
  8. 热电厂sis系统服务器升中标结果,电厂SIS系统简介
  9. 【小白】用python写一个单向聊天室
  10. 为什么我不建议在阿里云官网报考ACP/ACE认证?
  11. 业务流程图设计-Visio设计
  12. 视频剪辑技巧,视频旋转/翻转视频最简单的操作
  13. 【 [mmdetection] 如何在训练中断后,接着上次训练?】
  14. 【科技橙就新商业】淘系技术走进四川大学,讲述淘宝天猫的前端故事
  15. 如何在一夜之间获得成功:我「从无到有」的 5 年 [英文版]
  16. PHP使用QQ邮箱发送邮件无需SMTP服务器
  17. 数字签名、证书,RSA加密、解密
  18. 案例 | 中央企业数字化转型实践
  19. mysql xtrabackup_编写脚本令Xtrabackup对MySQL数据进行备份的教程
  20. 什么是WKT和WKB

热门文章

  1. PHP递归实现层级树状展现数据
  2. 1.6数组-像素翻转
  3. Python List Comprehension
  4. 简单方法解决缓存雪崩问题
  5. linux设备模型之mmc子系统
  6. NDK-r17c编译FFmpeg4.3(支持硬编解码与neon)(七)
  7. android源码灭屏时蓝牙自动配对
  8. Android Camera数据流分析全程记录(overlay方式二)
  9. 深度学习自学(三十九):基于对抗网络判别能力正则化的半监督生成方法
  10. 视频编解码(七):profilelevel简介、ffmpeg如何控制profilelevel、编码效率