V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
mikicomo
V2EX  ›  问与答

关于“==”和 equals 的一些疑惑

  •  1
     
  •   mikicomo · 2016-03-05 19:30:33 +08:00 · 1933 次点击
    这是一个创建于 2983 天前的主题,其中的信息可能已经有所发展或是发生改变。

    “==”和 java.lang 中默认的 equals 实现既然都是对于内存空间中地址的比较,那么为什么可以使用
    i == 1这样的写法来判断 i 和 1 是否相等呢?以前倒是从来没有考虑过这个问题,求教下 V 友。

    19 条回复    2016-03-16 19:34:46 +08:00
    ovear
        1
    ovear  
       2016-03-05 19:46:56 +08:00
    i 是什么 Integer ? 基本类型可以
    FinalDream
        2
    FinalDream  
       2016-03-05 19:51:54 +08:00
    基本类型都在栈里
    jsyangwenjie
        3
    jsyangwenjie  
       2016-03-05 20:08:15 +08:00
    基本类型
    mikicomo
        4
    mikicomo  
    OP
       2016-03-05 20:10:17 +08:00   ❤️ 1
    @ovear
    @FinalDream
    哦哦,所以意思是说,对内存空间地址的比较是相对于“引用”而言的?
    ovear
        5
    ovear  
       2016-03-05 20:13:14 +08:00
    @mikicomo 参见 Cache Pool , Java 在创建这些类型的对象的时候,内部有个表,如果不存在就创建,存在就直接指向。
    还是比较内存地址。
    mikicomo
        6
    mikicomo  
    OP
       2016-03-05 20:16:43 +08:00
    @ovear 哦哦,虽然暂时还不是很明白(琢磨着也不一定看得懂 Cach Pool ),但是 mark 了(果然是一个小细节都不能放过啊,以前很理所应当的 逻辑运算符号也有这么大的讲究,)
    wmlhust
        7
    wmlhust  
       2016-03-05 21:48:13 +08:00
    对于基本类型是直接比较值的吧
    对于对象,默认的 equals 是比较引用指向的对象地址
    SoloCompany
        8
    SoloCompany  
       2016-03-05 22:01:52 +08:00 via iPad
    基本类型和 object 完全是两个世界,==操作符的定义对于基本类型和 object 也是完全无关的
    otakustay
        9
    otakustay  
       2016-03-06 13:13:36 +08:00 via iPhone
    @ovear 不是 cache 的关系吧, primitive 的==操作就是内存比较
    ovear
        10
    ovear  
       2016-03-06 14:10:36 +08:00
    @otakustay 是 cache 关系,基本类型都是保证内存中有一个唯一实例。
    但是包装类型可以有多个实例。
    比如说 new Integer(1);
    这个 Integer 本身是新的,但是内部指向的这个 基本类型 1 是唯一确定的。
    otakustay
        11
    otakustay  
       2016-03-06 19:59:30 +08:00
    @ovear 你说的是 Integer ,这是一个 object 类型,而楼主表达的是 1 ,这是一个 primitive 类型。==操作符对这两类使用的逻辑是不同的, Integer 是引用比较,因为 cache 的原因一般都会成功,正如你说的;而 primitive 是内存值比较,和 cache 没有啥关系, int 在做==运算的时候也不会进行装箱转为 Interger
    同时, Integer 的 cache 也并不可靠,你可以试试
    Integer a = new Integer(12);
    Integer b = new Integer(12);
    System.out.println(a == b);
    这并不会给你想要的结果
    ovear
        12
    ovear  
       2016-03-06 20:51:25 +08:00
    @otakustay 关于你说的这个问题,很明显你是没有理解好 Java 的 Cache Pool 以及 Java 的自动拆装箱

    Integer a = 12;
    Integer b = 12;
    Integer c = new Integer(12);
    Integer d = 12;

    a==b==d
    c 和 abc 任意一个都不等

    这个才是 cache pool ,建议你看一下相关资料,其他包装类型,包括 String 也有类似的机制

    同时注意我上面的话

    基本类型都是保证内存中有一个唯一实例。

    而 包装类型

    保证的是,默认情况下会使用同一个实例,但是你强制使用 new 来创建包装类型, Java 就会忽略 Cache ,直接帮你创建,但是包装类型内部指向的 基本类型 是一样的。


    所以不管是基本类型,还是包装类型,比较的都是内存地址。只不过 Java 保证基本类型在内存中有唯一实例,才使得 == 操作符表现出来的行为像是值比较。

    (如有错误欢迎指正)
    colincat
        13
    colincat  
       2016-03-06 21:56:15 +08:00 via iPhone
    Intger i=100,如果整型字面量的值在-128 到 127 之间,那么不会 new 新的 Integer 对象,而是直接引用常量池中的 Integer 对象
    otakustay
        14
    otakustay  
       2016-03-07 11:24:46 +08:00
    @ovear 我理解楼主说的是下面这个问题:

    int i = 1;
    int j = 1;
    i == j;

    这里和 Integer 一点关系也没有, Integer 怎么工作我自然知道。这里的 i 和 j 的内存地址不一样,甚至把 i 通过参数传给另一个函数地址也不同( pass by copy ),但它们可以通过==运算
    otakustay
        15
    otakustay  
       2016-03-07 11:26:55 +08:00
    @ovear 另外你试试

    Long a = 1234567890;
    Long b = 1234567890;
    a == b;

    不要说基础类型都有 Cache , Cache 是非常有限的
    mikicomo
        16
    mikicomo  
    OP
       2016-03-07 16:48:05 +08:00
    @ovear
    @otakustay
    没想到一个问题引出两个大大的激烈讨论....
    不过我的本意是
    int i =1;
    i == 1
    这样的, otakustay 大大的理解可能有些偏差,不过也正因为如此再次给我打开了新世界的大门...!又接触到了更深一层的东西(虽然简单的还没搞定..)
    ovear
        17
    ovear  
       2016-03-07 18:49:29 +08:00
    @otakustay Long 并不是基础类型,另外多看文档,范围讲的很清楚。
    http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

    @mikicomo
    @otakustay

    如果是关于
    int a = 1;
    int b = 1;
    这两个基本类型的问题,我之前的理解有问题,之前不知道在哪本书和 zhihu 上看到了,对于基本类型也有个这种东西。但是经过 @大神 之后,证明我我的说法有问题。

    基本类型不一定会具备内存地址,可能还会存在于寄存器当中。 http://blog.csdn.net/lm2302293/article/details/6713147
    部分类型在 byte code 中是有常量的


    0x02
    iconst_m1
    int 型常量值-1 进栈
    0x03
    iconst_0
    int 型常量值 0 进栈

    具体、更专业的说法参考 https://www.zhihu.com/question/26711836/answer/89610502
    otakustay
        18
    otakustay  
       2016-03-07 21:55:42 +08:00
    @ovear 纯技术讨论哈
    Long 不是基础类型你前面说的 Integer 自然也不是了,不明白这里的矛盾点在哪里
    范围当然讲得很清楚,正是因为有这个清楚的范围,所以==依赖 Cache 的存在运用在 Integer 等对象类型上不就是一个 bad practice 么……正确来说,我们任何时候都不应该提倡对 Integer/Long 这样的类型用==操作符才对
    tedyhy
        19
    tedyhy  
       2016-03-16 19:34:46 +08:00 via Android
    @ovear 犀利
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3154 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 00:43 · PVG 08:43 · LAX 17:43 · JFK 20:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.