深入理解String和intern方法

来源:互联网 发布:ubuntu 17.10 安装后 编辑:程序博客网 时间:2024/05/01 23:23

定义字符串: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”;即:创建了2String对象一个是String池中创建了一个abc对象 在堆内存中创建了一个abc对象。

 

二、Stringintern()方法

 

是否记得方法区中运行时常量池和class文件中常量池的区别(运行时常量池保持着动态性,举的例子就是intern方法),intern先在常量池中查找是否存在一个对象,存在了就返回String池中对象的引用。如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。对于任何两个字符串 和 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

原创粉丝点击