Integer类型数据的比较

Java Integer缓存机制揭秘
本文深入探讨Java中Integer缓存机制,解释Integer对象在-128至127范围内的缓存原理,以及valueOf方法如何利用该缓存提高性能。通过实例演示不同情况下Integer对象的内存分配和引用比较,帮助理解Integer对象的使用和潜在陷阱。

我们在做Integer数据比较的时候,会有意想不到的结果,通过看Integer的源码,问题迎刃而解。这里的论述建立在jdk版本是1.8

Intger类有个静态内部类IntegerCache,是用于缓存Intger对象的。这里会缓存-128 到127的数据。

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;
            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() {}
    }

我们再看Integer.valueOf(int i)方法,如果请求的对象是-128-127之间,则直接返回缓存中的对象,如果不在这个区间,则会新建一个对象返回。

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

我们运行下栗子:

package com.leadbank.util;

public class IntegerTest {

    /**
     * Integer,初始化的时候会在缓存里存入-128-127的数据,只要
     * 通过Integer.valueOf(x)获取数据在这个返给内,都会从缓存中获取
     * @param args
     */
    public static void main(String[] args) {
        Integer a = new Integer(4);//只要自己new了,就会自己开辟内存空间
        Integer b =4;//会被编译器解析为Integer b = Integer.valueOf(4);
        System.out.println("new Integer(4)=Integer 4:"+(a==b));
        int c = 4;//会被解析为a.intValue() == c
        System.out.println("new Integer(4)=int 4:"+(a==c));
        Integer d = Integer.valueOf(4);
        //false,因为a开辟了自己的内存空间,没有从缓存中获取
        System.out.println("new Integer(4)=Integer.valueOf(4):"+(a==d));
        Integer e = 4;
        System.out.println("Integer 4 = Integer 4:"+(b==e));//true

        //结果true
        Integer _nagative_first_equal_128 = -128;
        Integer _nagative_second_equal_128 = -128;
        System.out.println("_nagative_first_equal_128=_nagative_second_equal_128:"+(_nagative_first_equal_128==_nagative_second_equal_128));

        //结果false
        Integer _nagative_first_equal_129 = -129;
        Integer _nagative_second_equal_129 = -129;
        System.out.println("_nagative_first_equal_129=_nagative_second_equal_129:"+(_nagative_first_equal_129==_nagative_second_equal_129));


        //结果true
        Integer _first_equal_127 = 127;
        Integer _second_equal_127 = 127;
        System.out.println("_first_equal_127=_second_equal_127:"+(_first_equal_127==_second_equal_127));

        //结果false
        Integer _first_equal_128 = 128;
        Integer _second_equal_128 = 128;
        System.out.println("_first_equal_128=_second_equal_128:"+(_first_equal_128==_second_equal_128));
    }
}

 

<think> 首先,用户的问题是关于Java中Integer数据类型比较方法。用户提供了引用:[1]讨论了两个Integer对象大小的比较;[2]说明Integer和int比较时自动拆箱;[3]强调使用equals方法比较,并提到缓存范围。 用户要求我参考站内引用,但注释说这些引用仅供参考,不是用户的真正需求。我应该尽可能多地参考用户上一次的问题和我的回答。然而,用户的上一次问题是系统级指令,这是一个系统提示,不是之前的对话历史。所以,可能没有之前的对话历史。 回顾对话: - 第一条消息是系统级指令。 - 当前用户消息是:"参考站内引用:引用[1]:... 我想查找Java中Integer数据类型比较的方法和相关知识 请问Java中Integer数据类型比较方法" 用户明确说:"上述引用仅供参考,并不是用户真正的需求",并指示要参考用户上一次的问题和我的回答。但在这个上下文中,"用户上一次的问题"可能指的是这个指令之前的对话。然而,第一条消息就是系统指令,所以没有之前的用户问题。 因此,我应该专注于当前用户的问题:"请问Java中Integer数据类型比较方法"。 系统指令要求: - 所有行内数学表达式使用$...$格式。(但这里可能不涉及数学表达。) - 独立公式使用$$...$$并单独成段。(同样,可能不适用。) - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 此外,在回答结构上,系统指令的示例显示: - 内容清晰,逐步解决问题。 - 尽量保证回答真实可靠。 用户提供了三个引用: - [1]:比较两个Integer大小,包括方法介绍。 - [2]:Integer和int比较时自动拆箱。 - [3]:强制使用equals方法比较整型包装类,提到缓存范围。 用户说这些引用仅供参考,所以我需要基于Java知识提供准确信息,同时融入这些点。 关键点总结: 1. **比较两个Integer对象**: - 使用 `==` 运算符比较引用(内存地址),但在缓存范围内(-128到127)可能返回true,因为对象被复用。 - 使用 `equals()` 方法比较值是否相等。 - 使用 `compareTo()` 方法比较大小。 - 使用 `Integer.compare(int x, int y)` 静态方法。 2. **比较Integer和int**: - 当Integer和int比较时,Java会自动拆箱Integer为int,然后比较值。 - 如引用[2]所述:`i == j` 其中i是Integer,j是int,结果为true如果值相等。 3. **最佳实践**: - 如引用[3]所述,阿里巴巴Java开发手册推荐所有整型包装类比较使用 `equals()` 方法以避免坑点。 结构化回答: - **引言**:简要介绍Integer比较的重要性。 - **方法详解**: - 使用 `==` 运算符:讨论引用比较和缓存问题。 - 使用 `equals()` 方法:值比较。 - 使用 `compareTo()` 方法:比较大小。 - 使用 `Integer.compare()` 静态方法。 - 比较Integer和int:自动拆箱。 - **最佳实践**:推荐使用 `equals()` 或 `compareTo()`。 - **代码示例**:提供简单代码演示。 - **相关问题**:生成相关的问题。 添加引用标识: - 在回答中自然地添加 [^1], [^2], [^3] 引用用户提供的引用。 使用中文回答。 生成相关问题: - 系统指令要求生成相关问题,示例中有"§§相关问题§§"部分。 - 相关问题应与主题相关,如Java比较的最佳实践、缓存机制等。 最终输出结构: 1. 回答Java中Integer比较方法。 2. 结尾生成相关问题列表。 </think> ### Java中Integer数据类型比较方法 在Java中,`Integer`是`int`基本类型的包装类,比较其对象时需要特别注意引用比较和值比较的区别。错误地使用`==`运算符可能导致意外结果,因此理解各种比较方法至关重要。以下详细介绍常见的比较方法,包括引用比较、值比较、大小比较以及与`int`类型的交互。所有说明基于Java SE规范,并结合了常见的最佳实践。 #### 1. **使用 `==` 运算符比较引用** - `==` 用于比较两个对象的 **内存地址(引用)**,而不是实际值。由于`Integer`在特定范围内(-128到127)使用缓存机制复用对象,`==` 在该范围内可能返回`true`,但范围外一定比较引用。 - **示例代码**: ```java Integer a = 100; // 在缓存范围内 Integer b = 100; System.out.println(a == b); // true, 因为对象复用 Integer c = 200; // 超出缓存范围 Integer d = 200; System.out.println(c == d); // false, 引用不同 ``` - **为什么避免使用?** 缓存范围外,`==` 比较的是对象地址而非值,容易导致逻辑错误。阿里巴巴Java开发手册强制要求所有整型包装类比较使用 `equals` 方法而非 `==`,以确保值比较的可靠性[^3]。 #### 2. **使用 `equals()` 方法比较值** - `equals()` 方法比较两个 `Integer` 对象的 **内容值**,确保安全性。这是推荐的最佳实践,尤其用于对象间的值等值比较。 - **示例代码**: ```java Integer num1 = new Integer(50); Integer num2 = new Integer(50); System.out.println(num1.equals(num2)); // true, 值相等 ``` - **优点**: 不受缓存影响,适用于所有范围的值。引用[3]强调所有整型包装类比较都应优先使用此方法[^3]。 #### 3. **使用 `compareTo()` 方法比较大小** - `compareTo()` 是 `Comparable<Integer>` 接口方法,用于比较两个 `Integer` 对象的 **大小关系**。返回值为: - 负数:第一个对象小于第二个。 - 0:值相等。 - 正数:第一个对象大于第二个。 - **示例代码**: ```java Integer x = 30; Integer y = 40; System.out.println(x.compareTo(y)); // -1 (x < y) System.out.println(y.compareTo(x)); // 1 (y > x) ``` - **适用场景**: 适用于排序或条件判断,如集合操作。 #### 4. **使用 `Integer.compare()` 静态方法比较** - `Integer.compare(int x, int y)` 是一个静态方法,直接比较两个 `int` 值(或自动拆箱后的 `Integer`),返回大小关系。返回值规则同 `compareTo()`。 - **示例代码**: ```java System.out.println(Integer.compare(10, 20)); // -1 (10 < 20) System.out.println(Integer.compare(30, 30)); // 0 (相等) ``` - **优点**: 高效且避免对象创建开销,适合高性能场景。 #### 5. **比较 `Integer` 和 `int`** - 当 `Integer` 对象与 `int` 基本类型比较时,Java会自动拆箱 `Integer` 为 `int`,然后进行值比较。这适用于 `==`、 `>`、 `<` 等运算符。 - **示例代码**: ```java Integer obj = 888; int primitive = 888; System.out.println(obj == primitive); // true, 自动拆箱比较值[^2] ``` - **注意事项**: 自动拆箱仅在混合比较时发生;纯 `Integer` 对象比较仍需使用 `equals()` 或 `compareTo()`[^2]。 #### 最佳实践总结 - **值比较**:始终使用 `equals()` 方法以确保准确性,尤其缓存范围外。 - **大小比较**:使用 `compareTo()` 或 `Integer.compare()` 方法。 - **避免 `==`**:仅在明确需要引用比较或缓存范围内使用时谨慎采用。 - **性能考虑**:自动拆箱在与 `int` 比较时高效,但对象比较优先用 `equals()`。 通过以上方法,你可以安全可靠地处理 `Integer` 比较问题。如果涉及数学表达式(如值范围判断),可用LaTeX格式表示,例如值缓存范围: $[-128, 127]$[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值