深入探索 Java-String

1. 字符串常量池(Literal Pool)
   Java使用一个字符串常量池来统一保存字符串的字面值,这样可以复用,节省内存。
   字符串字字面值是一个由双引号括起来的字符序列。它是指向一个String实例的引用。
   比如 String s = “abc”。对于“abc”,它首先是一个String literal,它在创建之后,立即利用String的intern方法,装入到了字符串常量池并返回这个String 实例的引用给s。当你再次写abc”的时候,intern方法会先查看是否已有这个literal了,就会直接返回这个literal对应的String实例的引用。也就是说你循环1000变,内存里面也只有这么一个String literal以及他对应的String的实例。
  
2. 编译时计算和运行时计算的区别

   String s1 = "abc"; 
   String s2 = "abc"; 
   String s3 = s1 + s2;  // 运行时确定s3的值
   String s4 = "abc" + "abc";  // 编译时在常量池会生成字符串字面值“abcabc”
   String s5 = "ab" + "cabc";  // 编译时直接复用常量池中的字符串字面值“abcabc”
       
   System.out.println(s3 == s4);  // 返回false
   System.out.println(s4 == s5);  // 返回true
  
3. hashCode值
   Java对象统一存储在哈希表中,使用对象时会根据hashCode值去获取对象,如果两个不同对象的hashcode相同,会在哈希表中发生冲突,
   哈希表中会通过链表来存储这两个不同对象。
   Java对象的hashCode值是根据Java对象的内存地址计算出相应的方法,函数hashCode是父类Object的方法,
   调用的是native方法。
   a、如果两个对象相同(及a==b),那么它们的hashCode值一定要相同;
   b、如果两个对象的hashCode相同,它们并不一定相同;
4. String的equals()方法
   String类的equals()方法,覆写了Object类的equals()方法,判断当前字符串与传进来的字符串的内容是否一致。
   所以字符串相等的判断是用equals()方法,而不是使用==。
   String中的equals()方法源代码如下:
   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;
       }
       
        Object对象quals()方法源代码
        public boolean equals(Object o) {
                return this == o;//比较两个对象是否相等
        }
5. String 类为什么是final
       a. 字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
   如下面的代码所示,将会在堆内存中只创建一个实际String对象.
   String s1 = "abcd"; 
   String s2 = "abcd”;
   深入探索 Java-String_第1张图片

   假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.    

   b. 允许String对象缓存HashCode

   Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。

   字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码.
   c. 安全性
   String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。
 
参考文档
http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/

你可能感兴趣的:(Java)