深入理解String和intern方法

定义字符串:String str=”abc”; 和String str=new String(“abc”); 的区别:

String str="abc";
String str1=new String("abc");
String str2="abc";
System.out.println(str);
System.out.println(str1);//都输出abc
 
//牵涉到==和equal()方法false和true和true
System.out.println((str==str1));
System.out.println(str.equals(str1));
System.out.println((str==str2));

”两个字符串是否是相同的实例,而在新的jdk版本中“”运算符和equals的效果是一样的注意这里的效果一样是只针对字符串(String str1=”123” String str2=”wsd” 因为一般都是这样定义的!),而不是对象。

String重写的equals源码:

那么我们来分析上面的代码在jvm编译器中编译器为我们做了哪些我们不知道的工作。

堆(heap)和栈(jvm栈),Java语言使用内存的时候,栈内存主要保存以下内容:基本数据类型和对象的引用,而堆内存存储对象,栈内存的速度要快于堆内存。总结成一句话就是:引用在栈而对象在堆。

 public boolean equals(Object anObject) {
    if (this == anObject) {//一开始就使用了==的运算符来判断这两个对象是否相等
        return true;
    }
    if (anObject instanceof String) {//比较两个对象
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
       char v1[] = value;
       char v2[] = anotherString.value;
       int i = offset;
       int j = anotherString.offset;
       while (n-- != 0) {
           if (v1[i++] != v2[j++])
           return false;
       }
       return true;
        }
    }
     return false;
}

String类的本质是private final char value[], 是不可被继承的,再次String是特殊的封装类型,使用String时可以直接赋值,也可以用new来创建对象,但是这二者的实现机制是不同的。

String池: Java运行时维护一个String池,池中的String对象不可重复,没有创建,有则作罢。String池不属于堆和栈,而是属于常量池。

String str = “abc”; -->在String池中创建一个对象”abc”,然后引用时str指向池中的对象”abc”。

String str2= “abc”; -->因为”abc”已经存在于String池了,所以不再创建,str2指向“abc”

String str1=new String(“abc”); 可以分为String str1=new String(); Str1=”abc”;即:创建了2个String对象,一个是String池中创建了一个abc对象 在堆内存中创建了一个abc对象。
二、String的intern()方法

是否记得方法区中运行时常量池和class文件中常量池的区别(运行时常量池保持着动态性,举的例子就是intern方法),intern先在常量池中查找是否存在一个对象,存在了就返回String池中对象的引用。如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

String str1 = "a";    
String str2 = "bc";    
String str3 = "a"+"bc";   //常量+常量=常量,结果保存到常量池中 
String str5 = str1+“a”;//变量+常量=变量,所以str5不在常量池中    
String str4 = str1+str2;       
System.out.println(str3==str4);    
str4 = (str1+str2).intern();    
System.out.println(str3==str4);

字符串对象的创建方式有两种

String s1 = new String("");   //第一种始终不会入池的.
String s2 = "";              //第二种要看情况而定(等号右边如果是常量则入池,非常量不入池)

String s3 = "a" + "b"; //常量+常量=常量,所以会入池.
String s4 = s1 + "b";   //变量+常量!=常量,所以不会入池. 

一旦入池的话,就会先查找池中有无此对象.如果有此对象,则让对象引用指向此对象;如果无此对象,则先创建此对象,再让对象引用指向此对象.例如:String s5 = “abc”; //先在池中查找有无"abc"对象,如果有,则让s5指向此对象;如果池中无"abc"对象,则在池中创建一个"abc"对象,然后让s5指向该对象.

String str ="a"+"b"完全等同于String str="ab"; 

下面有个网上的例子:

public class Mud {   
    public static String hello(String[] strs, String s2) {   
        strs[0] = "<" + strs[0] + ">";   
        s2.toUpperCase();   
        return s2;   
    }   
    public static void main(String... args) {   
        String a = new String("t");   
        String[] b = new String[] { "t" };   
        String c = a.intern();   
        if (a.equals(b[0])) {   //两个对象的值是一样的
            System.out.print("1");   
        }   
        if (b[0] == c) {   //
            System.out.print("2");   
        }   
        if (a == c) {   //a是一个堆中对象,指向常量池中的“t”
            System.out.print("3");   
        }   
        a = hello(b, c);   
        System.out.print(a);   
        System.out.print(b[0]);   
        System.out.print(c);   
    }   
}

那么它的结果是:12t<t>t

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值