Jtoss Jtoss
首页
  • 数据结构与算法

    • 数据结构与算法 - 概述
    • 数据结构与算法 - 复杂度分析
    • 数据结构 - 线性表
    • 算法 - 常见排序算法
  • 代码规范

    • 代码简洁之道
    • 阿里巴巴开发手册
    • 谷歌Java编程风格指南
  • 设计模式

    • 编写高质量代码概述
    • 面向对象
    • 设计原则
    • 设计模式-创建型
    • 设计模式-结构型
    • 设计模式-行为型(上)
    • 设计模式-行为型(下)
    • 浅析框架源码中的设计模式
    • 业务框架实战案例
  • MySQL 基础

    • MySQL - 数据库设计规范
    • MySQL - 必知必会
  • MySQL 进阶

    • MySQL - 基础架构
    • MySQL - InnoDB存储引擎
    • MySQL - InnoDB缓冲池
    • MySQL - 事务与锁
    • MySQL - 索引
    • MySQL - 查询执行计划
    • MySQL - 性能优化
  • Redis 系列

    • Redis入门 - 基础相关
    • Redis进阶 - 数据结构
    • Redis进阶 - 持久化RDB和AOF
    • Redis进阶 - 事件机制
    • Redis进阶 - 事务
    • Redis进阶 - 高可用高可扩展
    • Redis进阶 - 缓存问题
    • Redis进阶 - 性能调优
  • Java 基础

    • Java 基础 - 知识点
    • Java 基础 - 面向对象
    • Java 基础 - Q/A
  • Java 进阶 - 集合框架

    • Java 集合框架详解
  • Java 进阶 - 多线程与并发

    • Java 并发 - 理论基础
    • Java 并发 - 线程基础
    • Java 并发 - 各种锁
    • Java 并发 - 关键字 volatile
    • Java 并发 - 关键字 synchronized
    • JUC - CAS与原子操作
    • JUC - 锁核心类AQS
    • JUC - 锁接口和类简介
    • JUC - 并发容器简介
    • JUC - 通信工具类
    • JUC - Fork-Join框架
    • JUC - 线程池
  • Java 进阶 - JVM

    • JVM - 概述
    • JVM - 类加载机制
    • JVM - 内存结构
    • JVM - 垃圾回收机制
    • JVM - 性能调优
  • Maven系列

    • Maven基础知识
    • Maven项目构建
    • Maven多模块配置
  • Spring 框架

    • Spring 框架 - 框架介绍
    • Spring 框架 - IOC详解
    • Spring 框架 - AOP详解
    • Spring 框架 - SpringMVC详解
  • Spring Boot 系列

    • Spring Boot - 开发入门
    • Spring Boot - 接口相关
  • Spring Cloud 系列
  • Mybatis 系列

    • Mybatis - 总体框架设计
    • Mybatis - 初始化基本过程
    • Mybatis - sqlSession执行过程
    • Mybatis - 插件机制
    • Mybatis - 事务管理机制
    • Mybatis - 缓存机制
  • 业务常见问题

    • Java 业务开发常见错误(一)
    • Java 业务开发常见错误(二)
    • Java 业务开发常见错误(三)
    • Java 业务开发常见错误(四)
    • Java 业务开发常见错误(五)
    • Java 业务开发常见错误(六)
  • IDEA系列

    • IDEA 2021开发环境配置
    • IDEA 快捷键
  • Git系列

    • git status中文乱码
  • 其他

    • Typora+Picgo 自动上传图片
    • hsdis 和 jitwatch
  • 实用技巧
  • 收藏
  • 摄影
  • 学习
  • 标签
  • 归档

Jason Huang

后端程序猿
首页
  • 数据结构与算法

    • 数据结构与算法 - 概述
    • 数据结构与算法 - 复杂度分析
    • 数据结构 - 线性表
    • 算法 - 常见排序算法
  • 代码规范

    • 代码简洁之道
    • 阿里巴巴开发手册
    • 谷歌Java编程风格指南
  • 设计模式

    • 编写高质量代码概述
    • 面向对象
    • 设计原则
    • 设计模式-创建型
    • 设计模式-结构型
    • 设计模式-行为型(上)
    • 设计模式-行为型(下)
    • 浅析框架源码中的设计模式
    • 业务框架实战案例
  • MySQL 基础

    • MySQL - 数据库设计规范
    • MySQL - 必知必会
  • MySQL 进阶

    • MySQL - 基础架构
    • MySQL - InnoDB存储引擎
    • MySQL - InnoDB缓冲池
    • MySQL - 事务与锁
    • MySQL - 索引
    • MySQL - 查询执行计划
    • MySQL - 性能优化
  • Redis 系列

    • Redis入门 - 基础相关
    • Redis进阶 - 数据结构
    • Redis进阶 - 持久化RDB和AOF
    • Redis进阶 - 事件机制
    • Redis进阶 - 事务
    • Redis进阶 - 高可用高可扩展
    • Redis进阶 - 缓存问题
    • Redis进阶 - 性能调优
  • Java 基础

    • Java 基础 - 知识点
    • Java 基础 - 面向对象
    • Java 基础 - Q/A
  • Java 进阶 - 集合框架

    • Java 集合框架详解
  • Java 进阶 - 多线程与并发

    • Java 并发 - 理论基础
    • Java 并发 - 线程基础
    • Java 并发 - 各种锁
    • Java 并发 - 关键字 volatile
    • Java 并发 - 关键字 synchronized
    • JUC - CAS与原子操作
    • JUC - 锁核心类AQS
    • JUC - 锁接口和类简介
    • JUC - 并发容器简介
    • JUC - 通信工具类
    • JUC - Fork-Join框架
    • JUC - 线程池
  • Java 进阶 - JVM

    • JVM - 概述
    • JVM - 类加载机制
    • JVM - 内存结构
    • JVM - 垃圾回收机制
    • JVM - 性能调优
  • Maven系列

    • Maven基础知识
    • Maven项目构建
    • Maven多模块配置
  • Spring 框架

    • Spring 框架 - 框架介绍
    • Spring 框架 - IOC详解
    • Spring 框架 - AOP详解
    • Spring 框架 - SpringMVC详解
  • Spring Boot 系列

    • Spring Boot - 开发入门
    • Spring Boot - 接口相关
  • Spring Cloud 系列
  • Mybatis 系列

    • Mybatis - 总体框架设计
    • Mybatis - 初始化基本过程
    • Mybatis - sqlSession执行过程
    • Mybatis - 插件机制
    • Mybatis - 事务管理机制
    • Mybatis - 缓存机制
  • 业务常见问题

    • Java 业务开发常见错误(一)
    • Java 业务开发常见错误(二)
    • Java 业务开发常见错误(三)
    • Java 业务开发常见错误(四)
    • Java 业务开发常见错误(五)
    • Java 业务开发常见错误(六)
  • IDEA系列

    • IDEA 2021开发环境配置
    • IDEA 快捷键
  • Git系列

    • git status中文乱码
  • 其他

    • Typora+Picgo 自动上传图片
    • hsdis 和 jitwatch
  • 实用技巧
  • 收藏
  • 摄影
  • 学习
  • 标签
  • 归档
  • Java 基础

    • Java 基础 - 谈谈 Java 平台
    • Java 基础 - 知识点
    • Java 基础 - 面向对象
    • Java 基础 - Q/A
    • 扩展 - int 和 Integer
    • 扩展 - final、finally、finalize
    • 扩展 - String、StringBuilder、StringBuffer
    • 扩展 - Exception 和 Error
    • 扩展 - 引用
    • 扩展 - 数值计算问题
    • 扩展 - 反射和动态代理
  • Java 进阶 - 集合框架

  • Java 进阶 - 多线程与并发

  • Java 进阶 - JVM

  • Java 进阶 - 版本特性

  • Java
  • Java 基础
Jason

扩展 - int 和 Integer

# int 和 Integer

int 是整型数字,是 Java 八大基本类型之一(Primitive types:short、int、long、char、byte、float、double、boolean)。Java 语言虽然号称一切都是对象,但原始数据类型是例外。

Integer 是 int 的包装类。它有一个 int 类型字段 value 存储数据,并且提供了基本操作,如运算(min、max、sam),int 和字符串之间的转换等。

在 Java 5 中,引入自动装箱和自动拆箱功能(boxing / unboxing),Java 可以根据上下文,自动进行装拆箱(int 到 Integer 和 Integer 到 int),极大简化了相关编程。

在 Java 5 进行了另一个改进: Integer 值缓存。通常构建 Integer 对象是调用构造函数 new Integer(1),直接 new 一个对象。但实际中发现大部分的数据操作都是集中在有限的、较小数值范围。因而 Java 5 中在 Integer 中新增了 valueOf() 静态方法,将某范围内的值缓存,之后直接从缓存中获取,无需创建新的对象。带来明显的性能改进。

由于存在缓存机制,所以在进行数值比较时可能出现:

Integer a1 = 100;  // 会自动编译为:Integer.valueOf(100)
Integer a2 = Integer.valueOf(100);
a1 == a2; // 结果为 true;

Integer b1 = Integer.valueOf(200);
Integer b2 = Integer.valueOf(200);
b1 = b2; // 结果为 false
1
2
3
4
5
6
7

由于 == 只比较对象的引用地址,且 a1 和 a2 都引用相同地址,所以相等。正确做法应该使用 equals 进行数值比较,如 b1.equals(b2); 原理是将包装类拆箱为原始数据类型进行比较: value == ((Integer)obj).intValue()

扩展:

  1. 通过 valueOf() 方法获取 Integer 对象
public final class Integer extends Number implements Comparable<Integer> {
    // 存储数据,final 不可变,保证了基本的信息安全和并发编程中的线程安全
    private final int value;

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
}
1
2
3
4
5
6
7
8
9
10

该范围在 Integer 的内嵌类 IntegerCache 静态类中实现,默认为 -128 到 127,最大值可以通过虚拟机配置参数进行设置:

-XX:AutoBoxCacheMax=<size>
1

而 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 property
        int h = 127;
        // 如果虚拟机有配置整数缓存最大值,则替换默认的 127
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        // 初始化缓存所有数值
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

这种缓存机制通用存在于其他包装类:

  • Boolean 缓存了 true/false 对应实例,确切说,只会返回两个常量实例 Boolean.TRUE/FALSE
  • Short 缓存了 -128 到 127 数值
  • Long 缓存了 -128 到 127 数值
  • Byte 数值有限,缓存所有, -128 到 127 数值
  • Character,缓存范围’\u0000’ 到 ‘\u007F’
  1. 自动拆箱和自动装箱

    自动装箱是一种语法糖,虽然写法不同,但在编译阶段根据上下文自动进行了一些转换,即生成相同的字节码

    Integer boxing = 1; // 实际会自动转换成 Integer.valueOf(1);  int 自动装箱为 Integer 包装类
    int unboxing = integer ++; // 实际会自动转换成 (integer ++).intValue(); Integer 自动拆箱为 int 基本类型
    
    1
    2

    需注意:在有性能要求的场合,避免无意中的装箱和拆箱。在性能极度敏感的场景一般会避免创建大量的对象以及提高处理速度,使用原始数据类型、数组来替换包装类和动态数组 ArrayList 等可以作为性能优化的备选项。例如:

    // 线程安全计数器
    class Counter {
        private final AtomicLong counter = new AtomicLong();  
        public void increase() {
            counter.incrementAndGet();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7

    可以使用原始数据类型改写为:

    class CompactCounter {
        private volatile long counter;
        private static final AtomicLongFieldUpdater<CompactCounter> updater = AtomicLongFieldUpdater.newUpdater(CompactCounter.class, "counter");
        public void increase() {
            updater.incrementAndGet(this);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
  2. 如果原型数据类型计算时,需考虑线程安全,可使用 AtomicInteger 或 AtomicLong 等线程安全类。

  3. Java 原始数据类型和引用类型局限性:原始数据类型和 Java 泛型并不能配合使用;无法高效地表达数据,也不便于表达复杂的数据结构,比如 vector 和 tuple;

#Java
上次更新: 2025-02-24
Java 基础 - Q/A
扩展 - final、finally、finalize

← Java 基础 - Q/A 扩展 - final、finally、finalize→

最近更新
01
开始
01-09
02
AI工具分享
01-09
03
AI 导读
01-07
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Jason Huang | 闽ICP备2025088096号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式