我是靠谱客的博主 活力外套,最近开发中收集的这篇文章主要介绍老生常谈-- String aa="aaa", String aa=new String("aaa");,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

老生常谈的问题

        String aa="aaa";
        String cc=new String ("aaa");
         的区别 ?
                
代码

public class T{

       public static void main(String args[]){
       String aa="aaa";
       String cc=new String ("aaa");
        }
   }
     1.通过java自带工具javap 得到运行使得指令集

    Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

  public static void main(java.lang.String[]);
  Code:
   0:   ldc     #16; //String aaa
   2:   astore_1

   3:   new     #18; //class java/lang/String
   6:   dup
   7:   ldc     #16; //String aaa
   9:   invokespecial   #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V

   12:  astore_2
   13:  return

   只看有关部分:

   0:   ldc     #16; //String aaa
   2:   astore_1
  
  String aa="aaa";    对应

  ldc:                 从常量池(加载类时,将数字、字符、字符创常量导入方法区,

                            具体存储请看有关jvm内存模型 资料) 中得到字符串对  象("aaa"),压入栈中;
  astore_1:       取栈中数据(赋值给aa)


  String cc=new String ("aaa");   对应
   3:   new     #18; //class java/lang/String
   6:   dup
   7:   ldc     #16; //String aaa
   9:   invokespecial   #20; //Method java/lang/String."<init>":(Ljava/lang/Stri
           
   3:   new     #18; //class java/lang/String 创建对象
   6:   dup   复制栈顶压入栈
   7:   ldc     #16; //String aaa
   9:   invokespecial   #20; //Method java/lang/String."<init>":(Ljava/lang/Stri  调用构造方法


  

   由此可知,aa 等内容就是常量池中字符串常量"aaa"的地址
             cc 是以字符串常量"aaa"为参数新构造的字符串对象


  
    由此 以下问题就显而易见了

     String aa="aaa";
     String bb="aaa";
     String cc=new String("aaa");
     System.out.println(aa==bb); true//aa,bb都是方法区中字符串常量那个对象,

                                                           一个地址 (aa==bb就相当于 aa==aa 或 bb==bb)
     System.out.println(aa=cc);  false //cc可以看成是以aa为参数,new的字符串

2.通过java 自带工具jmap(jdk1.6以后)查看此过程创建了几个对象

   jmap -histo {pid}
num     #instances         #bytes  class name
----------------------------------------------
11:          1951           46824  java.lang.String

若运行String aa="aaa"; 以后
num     #instances         #bytes  class name
----------------------------------------------
11:          1952           46848  java.lang.String

可以看到 增加了1个 String 实例,对象就是 aa指向的字符串常量对象

若运行String cc=new String("aaa"); 以后
num     #instances         #bytes  class name
----------------------------------------------
  11:          1953           46872  java.lang.String

可以看到 增加了2个 String 实例,其中包括 常量池中字符串常量对象 ,还有 new的cc对象

若运行String aa="aaa"; String cc=new String("aaa"); 以后
num     #instances         #bytes  class name
----------------------------------------------
  11:          1953           46872  java.lang.String
虽然两个语句都运行,但只增加了2个对象,常量池中字符串常量对象,new的cc对象

(常量池中字符串常量创建一次,并且共享数据)


ldc指令格式:ldc,index

ldc指令过程:

要执行ldc指令,JVM首先查找index所指定的常量池入口,在index指向的常量池入口,
JVM将会查找CONSTANT_Integer_info,CONSTANT_Float_info和CONSTANT_String_info入口。
如果还没有这些入口,JVM会解析它们。而对于上面的hahaJVM会找到CONSTANT_String_info入口,
同时,将把指向被拘留String对象(由解析该入口的进程产生)的引用压入操作数栈。


3.做下面测试(使用javap,和jmap工具,jdk版本1.6)

  

public static void main(String args[]){

            //10:          1935           46440  java.lang.String
    String aa="aaa";
            //10:          1936           46464  java.lang.String
    String bb="aa"+"a"; //编译时在class文件中编译器只保留"aaa" 字符串常量,可以通过javap命令知道
            //10:          1936           46464  java.lang.String
    String dd="aaa";
            //10:          1936           46464  java.lang.String
    String ee="bbb";
            //10:          1937           46488  java.lang.String
String cc=new String ("aaa");
            //10:          1938           46512  java.lang.String
          
          t();
}
public static void t(){
            //10:          1938           46512  java.lang.String
            String aa="aaa";
            //10:          1938           46512  java.lang.String
            String bb="aa"+"a";
            //10:          1938           46512  java.lang.String
            String dd="aaa";
            //10:          1938           46512  java.lang.String
            String ee="bbb";
            //10:          1938           46512  java.lang.String
            String cc=new String ("aaa");
            //10:          1939           46536  java.lang.String
}
    
注: 测试 aa==bb==cc true

 

 

最后

以上就是活力外套为你收集整理的老生常谈-- String aa="aaa", String aa=new String("aaa");的全部内容,希望文章能够帮你解决老生常谈-- String aa="aaa", String aa=new String("aaa");所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部