最近在很多文章中看到很多人问:String为什么是final的,所以自己写下这篇文章,来深入了解下。

  首先先了解两个问题:

Java中 final的定义:

  1.  Java的关键字final的含义存在着细微的区别,但是通常它是指"这是无法改变的"。不想做出改变可能处于两种理由:设计和效率。
  2. final 修饰的类是不被能继承的,所以 final 修饰的类是不能被篡改的。 

jdk源码String的解释:

    

java String 为什么设计成 final的 string为什么被定义为final_字符串

       字符串是常量。它们的值在它们创建之后是无法改变的。字符串缓冲区是支持可变字符串。由于字符串对象是不可变的,所以它们可以被共享。

   上述两个问题解释后,估计大家都有所了解了。那么我们可以知道是安全,共享,效率这三个方面。

   1)、确保它们不会在子类中改变语义。String类是final类,这意味着不允许任何人定义String的子类。
       换言之,如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。 
     2)、String 一旦被创建是不能被修改的,
      因为 java 设计者将 String 为可以共享的,下面这段是源码中的注释:

java String 为什么设计成 final的 string为什么被定义为final_字符串_02

 对应翻译:
/**
*字符串类表示字符串。所有
*在java程序中的字符串,如“ABC”,是
*实现为这个类的实例。
*
*字符串是常量,它们的值在它们之后不能更改
*创建。支持可变字符串字符串缓冲区。
*因为字符串对象是不可改变的,它们可以共享。

3)设计成final,JVM才不用对相关方法在虚函数表中查询,而直接定位到String类的相关方法上,提高了执行效率。 
     Java设计者认为共享带来的效率更高。

自己写了段代码测试:

public class StringTest {

    public static void main(String[] args) {
        String str = "abc";
        String str1 = new String("abc");
        System.out.println("str hashCode:"+str.hashCode());
        System.out.println("str1 hashCode:"+str1.hashCode());
        System.out.println(str.equals(str1));

    }
}

  测试结果:

str hashCode:96354
str1 hashCode:96354
true

总而言之:java.lang.String 引用的对象一定是 java.lang.String的对象,不是其它子类的对象,这样才能保证它的安全和效率。