专栏首页BAT的乌托邦【小家java】大杂烩---那些年我们一起躺过的坑

【小家java】大杂烩---那些年我们一起躺过的坑

1、概述

此篇博文没有具体的主题,主要针对于平时开发过程中遇到的一些小问题的记录,并且大都从源码的角度去解释为什么会报错。并且此篇博文是持续更新中。。。

2、栗子

1、包装类型的的> < =的比较

public static void main(String[] args) {
    Integer i = null;
    Integer i2 = null;
    System.out.println(i < i2); //java.lang.NullPointerException
}

包装类型能用比较运算符的根本原因:JDK5的自动拆箱。因此如果是是null的话,自动拆箱就报错了。所以在日常使用的时候一定要注意。特别是Interger和int比的时候,如果Interger为null,那必然空指针。从代码角度看是因为自动拆箱JVM会调用Interger的.intValue()方法,所以如果是null,就挂了

2、关于int值比较的一些问题 在日常编码中,经常会遇到Interger的比较问题(比如id相等),看下面例子

 public static void main(String[] args) {
   Integer i1 = 100;
   Integer i2 = 100;
   System.out.println(i1 == i2); //true
   Integer i3 = 200;
   Integer i4 = 200;
   System.out.println(i3 == i4); //false
 }

我们知道,对象比较用==的话比较的是地址值,所以咱们看看两者的地址值哈。

public static void main(String[] args) {
    Integer i1 = 100;
    Integer i2 = 100;
    System.out.println(System.identityHashCode(i1)); //2093631819
    System.out.println(System.identityHashCode(i2)); //2093631819
    Integer i3 = 200;
    Integer i4 = 200;
    System.out.println(System.identityHashCode(i3)); //2074407503
    System.out.println(System.identityHashCode(i4)); //999966131
}

各位看官,应该看出端倪了吧,这就是为什么第一个是true,第二个为false的最直接原因,但还不是最根本原因,下面容我介绍一下最根本原因,Interger内部有如下代码:

同理Long里面一样

如图可以看出,Interger在初始化的时候内部就维护了一个缓存:-128到127对象都给Cache了,所以当我们向上转型这些对象时,没有new而是从缓存拿的,所以就是上面的答案。当然,我们必须清楚,其实JVM自动装箱调用了valueOf方法:

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

我们发现,没有new而是从缓存拿,因此内存地址值肯定一样的。所以可以很好理解下面这两个现象了:

 public static void main(String[] args) {
     Integer i1 = new Integer(100);
     Integer i2 = new Integer(100);
     System.out.println(i1 == i2); //false 因为用了new关键字,一定开辟新内存的
     Integer i3 = new Integer(200);
     Integer i4 = new Integer(200);
     System.out.println(i3 == i4); //false
 }

这样比较也没有问题:

public static void main(String[] args) {
    int i1 = 100;
    int i2 = 100;
    System.out.println(i1 == i2); //true
    int i3 = 200;
    int i4 = 200;
    System.out.println(i3 == i4); //true
}

所以,综上所述,同类型的包装类型比较的时候,建议使用equals()方法。但是此处提醒一点:不同类型的equals肯定是false的,比如Interger和Long的对比,不要这么来:

 public static void main(String[] args) {
     Integer i1 = 100;
     Long i2 = 100L;
     System.out.println(i1.equals(i2)); //false
 }

这个虽然值一样,但结果肯定false。这里我贴一处源码,大家就能了解了:

我们发现他们都重写了equals方法,而类型相同是第一必须。so,以后比较的时候一定要注意类型一致啊

3、intValue(),Integer.valueOf(String s)和Integer.parseInt(String s)有什么区别? intValue()是把Integer对象类型变成int的基础数据类型; //一般由jvm自己调用 静态方法parseInt()是把String 变成int的基础数据类型; 静态方法valueOf()是把给定的String参数转化成Integer对象类型,依赖于parseInt()方法;

然后如果想得到一个小的Integer对象,但是Integer.valueOf的效率比new的效率高,因为valueOf有缓存。

综上所述,一般用Integer.parseInt(str),除非你要返回Integer类型,不然还有封装拆箱,性能多少会耗费些。

3、使用场景

持续更新中。。。

4、最后

整理出来的都是一些小细节,希望能帮助到大家

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【小家java】java8新特性之---函数式接口(Supplier、Consumer、Predicate、Function、UnaryOperator,通往高阶设计的好工具)

    首先,它还是一个接口,所以必须满足接口最基本的定义。但它是一个特殊的接口:SAM类型的接口(Single Abstract Method)。可以在调用时,使用一...

    YourBatman
  • 【小家java】java8新特性之---Stream API 详解 (Map-reduce、Collectors收集器、并行流、groupby多字段分组)

    Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。

    YourBatman
  • 玩转Spring Cache --- 开启基于注解的缓存功能@EnableCaching原理了解【享学Spring】

    缓存现已成为了项目的标配,更是面必问的知识点。若你说你的项目中还没有使用到缓存,估计你都不太好意思介绍你的项目。

    YourBatman
  • Java语法糖(一)

      语法糖(Syntactic Sugar):主要作用是提高编码效率,减少编码出错的机会。

    在周末
  • Java中Integer的详解

    在Java中有int和integer两种类型,简单的说Integer是int的引用类型,但是这个引用的类型比较特殊,下面看几个demo:

    付威
  • Golang语言为类型添加方法

    1 package main 2 3 import "fmt" 4 5 type Integer int 6 //给in类型添加 Less 方法...

    李海彬
  • 夯实Java基础系列8:深入理解Java内部类及其实现原理

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖
  • 再谈Integer对象比较

    在上一篇文章中介绍了Integer的特性及面试中常考的几个知识点,本篇文章再做些扩充。

    小诸葛
  • Java遍历Map对象的四种方式

    如果只需要map中的键或者值,你可以通过keySet或values来实现遍历,而不是用entrySet。该方法比entrySet遍历在性能上稍好(快了10%),...

    诺浅
  • 搞清楚一道关于Integer的面试题

    面试题3中的a=99相当于a=new Integer(99);重新给把一个新的对象引用地址给了a,所以a变了,最后输出是99。

    田维常

扫码关注云+社区

领取腾讯云代金券