Java面试知识点(十一)关于integer和string的==、equals判断

154 篇文章 5 订阅
150 篇文章 6 订阅

一、integer的==

public class Test03 {
 
     
    public static void main(String[] args) {
        
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
 
          
        System. out.println( f1 == f2); //true
        System. out.println( f3 == f4); //false
    }
}

当我们给一个 Integer 赋予一个 int 类型的时候会调用 Integer 的静态方法 valueOf。
Integer f1 = Integer.valueOf(100);
Integer f2 = Integer.valueOf(100);
Integer f3 = Integer.valueOf(150);
Integer f4 = Integer.valueOf(150);
思考:那么 Integer.valueOf()返回的 Integer 是不是是重新 new Integer (num); 来创建的呢?如果是这样的话,那么 == 比较返回都是 false,因为他们引用的堆地址不一样。

具体来看看 Integer.valueOf 的源码

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

从上面我们可以知道给 Interger 赋予的 int 数值在 - 128 - 127 的时候,直接从 cache 中获取,这些 cache 引用对 Integer 对象地址是不变的,但是不在这个范围内的数字,则 new Integer (i) 这个地址是新的地址,不可能一样的.

注意
Integer的默认值是null(对象的默认值都是null)
int类型默认值是0.

二、string的==

  1. String str=new String (“abc”) 和 String str=“abc” 的字符串 “abc” 都是存放在堆中,而不是存在栈中。

  2. 其实在在 java 中有一个 “字符数据池” 的内存管理机制。

  3. String str=“abc”,执行这句话时,会先去 “字符数据池” 搜索时候有 “abc” 这个字符串,如果有,则将字符串的首地址赋值给 str,如果没有,生成一个新的字符串 “abc” 并且将首地址赋值给 str;

  4. String str=new String (“abc”),执行这句话时,会现在堆里面生成一个对象,str存储的是这个对象的地址,同时,会去查看字符常量池中是否存在该字符串,如果存在就不处理,如果不存在,还会在字符常量池中生成一个相同的字符串。

  5. 由以上分析可知,String str=“abc” 和效率要高于 String str=new String (“abc”),因为如果有重复的字符串时,第一种方式可以节省空间。

  6. 下面举例说明一下,好好看看结果,仔细分析原因,上面已经说明的很清楚了:

public class Test{
 public static void main(String args[]){
  String s1=new String ("abc");// 直接在堆中生成新的 “abc”
  String s2=new String ("abc");// 直接在堆中生成新的 “abc”
  String s3="abc";// 先去 “字符数据池” 搜索时候有 “abc” 这个字符串,如果有,则将字符串的首地址赋值给 s3,如果没有,则在 “字符数据池” 中生成一个新的字符串 “abc” 并且将首地址赋值给 s3;  
  String s4="abc";// 去 “字符数据池” 搜索时发现了上一步生成的 “abc” 这个字符串,把该字符串首地址赋值给 s4,这时其实 s3 和 s4 指向同一个字符数据池中的 “abc”
  System.out.println(s1==s2);
  System.out.println(s1==s3);
  System.out.println(s2==s3);
  System.out.println(s3==s4);
 }
}

结果:
false
fasle
false
true

总结

综上所述,创建字符串有两种方式:两种内存区域(pool,heap)

String 对象的不可变性

toUpperCase () 会对当前对象进行检查 如果不需要转换直接返回当前对象,否则 new 一个新对象返回;
replace () 如果两个参数相同,则直接返回,否则 new 一个新对象

1," " 引号创建的字符串在字符串池中

2,new,new 创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址

补充:

  • String s1 = new String (“abc”); 这句话创建了几个字符串对象?
    将创建 1 或 2 个字符串。如果池中已存在字符串文字 “abc”,则堆中只会创建一个字符串 “s1”。如果池中没有字符串文字 “abc”,那么它将首先在池中创建,然后在堆空间中创建,因此将创建总共 2 个字符串对象。
  • String s = “aaa” + new String(“bbb”);
    上面创造了几个对象呢
    答案是 4 个,ps: 前提是 pool 都没有这四个字符串
    “aaa” 一个对象(池)
    new Sring () 一个对象(堆)
    “bbb” 一个对象(池)
    “aaa” + new new Sring () 一个对象(池)

例如:
String str1=”java”; // 指向字符串池
String str2=”blog”; // 指向字符串池

String s=str1+str2; //s 是指向堆中值为 “javablog” 的对象,+ 运算符会在堆中建立来两个 String 对象,这两个对象的值分别是 “java” “blog”. 也就是说从字符串池中复制这两个值,然后在堆中创建两个对象,然后再建立对象 s, 然后将 “javablog” 的堆地址赋给 s.

System.out.println (s==”javablog”); // 结果是 false。

Jvm 确实对型如 String str1=”java”; 的 String 对象放在常量池里,但是它是在编译时那么做的,而 String s=str1+str2; 是在运行时刻才能知道,也就是说 str1+str2 是在堆里创建的,所以结果为 false 了。


如果改成一下两种方式:

String s=“java” + “blog”; // 直接将 “javablog” 放入字符串池中,System.out.println (s==”javablog”); 的结果为 true,
String s=str1+ “blog”; // 不放入字符串池,而是在堆中分配,System.out.println (s==”javablog”); 的结果为 False

三、基本类型和包装类的==和equals(涉及拆装箱)

1、基本型和基本型封装型进行 “= =” 运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此 Integer (0) 会自动拆箱为 int 类型再进行比较,显然返回 true;
2、两个 Integer 类型进行 “= =” 比较,如果其值在 - 128 至 127,那么返回 true,否则返回 false, 这跟 Integer.valueOf () 的缓冲对象有关,这里不进行赘述。
3、两个基本型的封装型进行 equals () 比较,首先 equals () 会比较类型,如果类型相同,则继续比较值,如果值也相同,返回 true
4、基本型封装类型调用 equals (), 但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行 3 中的比较。
5、对于equal方法来说,如果没有重写过,那么就是相当于==,也就是直接比较地址的,所以呢,如果没有重写equal方法的对象调用equal方法,是直接比较对象地址的。

关于==和equal 还可以看(一)https://blog.csdn.net/qq_33945246/article/details/89922517

  • 18
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值