Java之String关键字解析

1. String类

  • String类是final类,即String类不能被继承,并且它的成员方法都默认为final方法。

Java中被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。

  • String类底层是char数组来保存字符串的,对String对象的任何改变都不会影响到原对象,相关的任何change操作都会生成新的对象。

2. 字符串常量池

在class文件中有一部分用来存储编译期间生成的字面常量以及符号引用,这部分就叫做class文件常量池,在运行期对应着方法区的运行时常量池。

JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存就被称为字符产常量池或字符串字面量池。

2.1 工作原理

当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。

2.2 实现前提

字符串常量池实现的前提条件:

  • Java中String对象不可变,可以安全保证多个变量共享同一个对象。
    若String对象可变,则一个引用操作改变了对象的值,那其它的变量也会被影响,导致不一致性

3. 实例

String str1 = "hello"; // str1指的是方法区中的字符串常量池中的"hello",编译时期就知道
String str2 = "he" + new String("llo"); // str2必须在运行时才知道str2是什么,所以其指向的是堆里定义的字符串"hello",这两引用不同。
str1.equals(str2); // 返回true,因为String类重写了equals方法
//编译器编译期不知道"he" + new String("llo")的内容是什么,所以不敢贸然把"hello"对象的引用赋给str2
String str3 = "he" + "llo";
str1.equals(str3); // 返回true
new String("xy") // 实际上创建了2个String对象,一个使用"xy"通过双引号创建的(在字符串常量池,编译期),另一个通过new创建的(在堆里,运行时),创建时期不同。
String s = "a" + "b" + "c"; // "a","b","c" 都是常量,编译时就直接存储他们的字面值,而不是他们的引用,所以编译期就直接将他们连接的结果提取出来变成"abc"了。
package io.itracybryant.fd;

public class StringInEqual {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        String d = "ab" + "c";
        String d1 = "ab";
        String d2 = "c";
        String e = d1 + d2;
        String f = "ab" + new String("c");
        System.out.println(a == b);
        System.out.println(a == c);
        System.out.println(a == d);
        System.out.println(a == e);
        System.out.println(a == f);
        System.out.println("---------------------------");
        System.out.println(a.equals(b));
        System.out.println(a.equals(c));
        System.out.println(a.equals(d));
        System.out.println(a.equals(e));
        System.out.println(a.equals(f));
        System.out.println("---------------------------");
        System.out.println(a.hashCode() == b.hashCode());
        System.out.println(a.hashCode() == c.hashCode());
        System.out.println(a.hashCode() == d.hashCode());
        System.out.println(a.hashCode() == e.hashCode());
        System.out.println(a.hashCode() == f.hashCode());
    }
}

Java之String关键字解析