Long 封装类型比较是否相同

写在开始:

Long 封装类型比较,最好使用 compareTo 函数、equals函数或longValue函数获取基本类型long的值再比较。

问题描述:封装类Long类型的变量,相同的值,结果比较缺不相等。

直接上代码:

public static void main(String[] args) {
    Long c = 128L;	//等同于 Long c = Long.valueOf(128);
    Long d = 128L;
    System.out.println("c == d : " + (c == d));         //false
    System.out.println("c.compareTo(d) : " + c.compareTo(d));   //0
}

//输出结果:
c == d : false
c.compareTo(d) : 0

换代码,注意c、d变量的值

public static void main(String[] args) {
    Long c = 127L;	//等同于 Long c = Long.valueOf(128);
    Long d = 127L;
    System.out.println("c == d : " + (c == d));         //true
    System.out.println("c.compareTo(d) : " + c.compareTo(d));   //0
}

//输出结果:
c == d : true
c.compareTo(d) : 0

结论:

值范围在[-128,127]内的Long对象存放在常理池中。

两个Long封装类型的变量比较是否相等时,当值范围在[-128,127]间时,用 == 比较相同的值,是相等的。

超出这个范围使用 == 结果便不在正确。

应该使用compareTo

public int compareTo(Long anotherLong) {
    return compare(this.value, anotherLong.value);
}

public static int compare(long x, long y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

【x.compareTo(y) 返回结果:-1:x < y, 0:x == y, 1:x > y】

或使用equals

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();	//转成基础类型long进行值比较
    }
    return false;
}

另一种使用Long.longValue获取基本类型值再比较

分析:

        Long c = 128L; (等同于 Long c = Long.valueOf(128);)

        首先在栈中声明了一个基础类型long 128l, 然后调用Long.valueOf() 生成 Long类型的 128l,再赋值给c。

        (tips:怎么知道会调用Long.valueOf()的?见文末)

Long.valueOf() 代码内容:

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}

从上面代码可以看出,当long类型的值超出【-128,127】范围时,会执行 new 操作生成新的Long对象,这就导致c、d即使均赋值128l,但用==比较却不相等的原因,因为==对于引用类型只比较内存地址。

在【-128,127】范围内的值,会从常量池LongCache.cache 数组中获取对象,所以c、d赋值127l时,实际是从LongCache.cache数组中获取了同一个Long对象,所以==比较是相等的。

private static class LongCache {
    private LongCache(){}
    //定一个了一个长度为256的数组
    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        //将【-128,127】的Long对象放到cache[]中
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

另一种情况,见代码

public static void main(String[] args) {
    Long a = 1000L;
    long b = 1000L;
    System.out.println("a == b:" + (a == b));	//true
}

//输出结果:
a == b:true
a==b 比较时,a会先调用Long.longValue 获取基本类型long的值,然后在于b进行比较,所以 a==b 为true

最后:

Long c = 128L; 怎么知道调用Long.valueOf函数的?

查看class文件的字节码。命令:javap -c class文件名称(不用带.class)

最直观的方式,打断点。

//源码
package com.experiment;
public class LongTest {

    public static void main(String[] args) {
        Long a = 128L;
    }
}

//class
package com.experiment;
public class LongTest {
    public LongTest() {
    }

    public static void main(String[] args) {
        Long a = 128L;
    }
}

//字节码
public class com.experiment.LongTest {
  //构造函数
  public com.experiment.LongTest();		
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  
  //mian主函数
  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #2                  // long 128l	//在栈中分配一块空间,类型为long 值为128l
       3: invokestatic  #4                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;	//调用静态方法 Long.valueOf 
       6: astore_1							//将栈顶引用类型值保存到局部变量1中。
       7: return
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值