Java String

作者: DjangoW | 来源:发表于2018-08-11 10:58 被阅读0次

    String在JAVA中是以final修饰的char数组实现的,所以一旦创建了某个string,不可修改。而且String不能被继承(final)。

    先来看第一个例子:

    String b = "b";
    String anotherB="b";
    String newB = new String("b");
    b == anotherB //true
    b == newB //false
    

    其中原委:

    b在java加载class的时候会被放入方法区(Method Area)的常量池(Constant Pool)中,之后通过b赋值的变量都被当作constant,直接指向常量池中的内存地址,所以banotherB指向同一个地址。

    new String("b")则创建了一个instance,JVM会在执行这条语句的时候(Runtime)在堆(Heap)中为其分配内存,所以和b指向的不是同一个地址。

    第二个例子:

    String s = "a";
    for(int i =0; i < 10; i++)
        s+="a";
    

    编译期间,上段代码会Compiler被优化成:

    String s = "a";
    for(int i =0; i < 10; i++){
        StringBuilder sb = new StringBuilder(s);
        sb.append("a");
        s=sb.toString();
    }
    

    创建了10个StringBuilder实例,所以在loop中不要用string进行操作,不然会在Heap中创建大量短生命周期的instance而加重GC的负担。

    第三个例子:

    String s = "a" + "b" +"c";
    

    这条语句java创建了多少对象?

    一个!因为Compiler会针对这种语句做优化,所以上述语句等价于 String s = "abc";其中abc被当作const处理,加载进jvm的时候放入方法区常量池,s指向该const的地址。所以s == "abc"是true。

    另一个例子:

    String a = "a";
    String ab = a + "b";
    System.out.println(ab == "ab"); //false
    

    因为ab赋值中a是变量,编译器不会针对优化。

    String VS. StringBuilder VS. StringBuffer

    • StringBuilder是可变的(mutable),非线程安全。

    • String是不可变的(immutable)

    • StringBuffer是可变的,而且线程安全(thread-safe),因为其内的方法都被synchronize关键字修饰,保证每次只有一个线程操作该对象。因为每次操作都要先加monitor锁,所以其效率要差于StringBuilder.

    String 为什么设计成immutable的?

    1. literal很常用,设计成final在JVM加载.class类文件的时候会把字符串放到方法区的常量池中,相同的字符串共用同一个常量池地址。
    2. String设计成final的会保证hashCode()也不会改变,从而可以在String中缓存其计算的hash code,不必每次都重新计算。
    3. 如果String是mutable的话,其hashCode()计算的结果也会变,在作为key存取Map的话就会出问题:改变之后的string变量作为key检索不出之前存入的value

    相关文章

      网友评论

        本文标题:Java String

        本文链接:https://www.haomeiwen.com/subject/ryorbftx.html