运行结果:

  5)除上述五点之外,对于字符串以及基本类型的包装类(Byte,Short,Integer,Long,Character,Float,Double和Double),Java允许他们以直接量来创建Java对象,eg:Integer in = 5;

  2、JVM对字符串变量的处理

  在Java中,我们经常会用到字符串类型,关于字符串类型,有这么三个类型:String , StringBuffer, StringBuilder,那么为什么一个简单的字符串类型要分为这三种呢?JVM对他们的处理有是怎样的呢?

  1)String,不可变的字符串

  ① 我们先来看一下基本的笔试面试题:String javaStr = new String("小学徒的成长历程");这条语句创建了几个字符串对象?

  答案是两个,一个是“小学徒的成长历程”这个直接量对应的字符串对象,一个是由new String()构造器返回的字符串对象。

  那么究竟为什么是两个呢?为什么会有直接量对应的字符串对象呢?好啦,言归正传。其实这个与JVM对字符串变量的处理有关了。

  对于Java程序中的字符直接量(eg:String javaStr = "小学徒的成长历程"),JVM会使用一个字符串池来保存他们,当第一次使用某个字符串直接量时,JVM会将它放入字符串池进行缓存。当程序再次需要使用该字符串时,无须重新创建一个新的字符串,而是直接引用变量执行字符串中已有的字符串。但是对于使用构造器进行初始化的字符串(eg :String javaStr = new String("小学徒的成长历程")),因为凡是通过构造器创建的对象都会进行内存分配,所以他不会指向缓存池中已有的对象而指向新的对象,这样会造成缓存池中存在多个值相同的字符串对象,浪费了资源。

public class Test{
   
     public static void main(String[] args) {
         //通过构造器进行初始化,如果是第一次,他同样会在缓存池中缓存该字符串
         //但是他依旧另外创建一个对象并指向该对象
         String newStr = new String("小学徒的成长历程");
         //javaStr的值是字符串直接量
         //所以,javaStr指向字符串缓存池中的"小学徒的成长历程"字符串
         String javaStr = "小学徒的成长历程";
         //由于缓存池中已经有了"小学徒的成长历程"字符串
         //所以,anotherStr也指向字符串缓存池中的"小学徒的成长历程"字符串
         String anotherStr = "小学徒的成长历程";
   
         System.out.println("javaStr == anotherStr : " + (javaStr == anotherStr));    //判断两个字符串是不是指向同一个对象
         System.out.println("newStr == anotherStr  : " + (newStr == anotherStr));
         System.out.println("newStr == javaStr     : " + (newStr == javaStr));
     }
 }

  运行结果:

  上面的测试代码块执行后,他在内存中的分配情况是这样的: