`
fujinbing
  • 浏览: 239899 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

老生常谈-- String aa="aaa", String aa=new String("aaa");

    博客分类:
  • java
阅读更多

老生常谈的问题

        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 s = new String(” a “) 到底产生几个对象?

    老生常谈的一个梗,到2020了还在争论,你们一天天的,哎哎哎,我不是针对你一个,我是说在座的各位都是人才! 上图红色的这3个箭头,对于通过new产生一个字符串(”宜春”)时,会先去常量池中查找是否已经有了”...

    老生常谈Java String字符串(必看篇)

    使用 new 关键字的标准构造方法则是通过 `String str = new String("hello");`。 String 字符串常量池 在 Java 中,String 字符串对象的创建过程中会涉及到字符串常量池的概念。字符串常量池是一种特殊的存储结构...

    老生常谈spring boot 1.5.4 日志管理(必看篇)

    Spring Boot 是一个流行的 Java 框架,它简化了创建生产级别的、基于Spring的应用程序的过程。在Spring Boot 1.5.4版本中,日志管理是开发过程中的重要环节,因为它提供了对应用程序运行时行为的洞察。...

    老生常谈JS中的继承及实现代码

    JS虽然不像是JAVA那种强类型的语言,但也有着与JAVA类型的继承属性,那么JS中的... var obj1 = new Fn(AAA); var obj2 = new Fn(BBB); console.log(obj1.show==obj2.show); //false 此时可以看出构造函数的多次创建

    老生常谈ProgressBar、ProgessDialog的用法

    - 常用方法有`setMessage(String)`设置提示信息,`show()`显示对话框,`dismiss()`关闭对话框。 7. ProgressBar的关键方法: - `setProgress(int)`:设置当前进度。 - `setSecondaryProgress(int)`:设置次要...

    老生常谈Java字符串进阶(必看篇)

    `String`对象的创建可以通过字面量(如`"hello"`)或构造函数,如`new String("example")`。`String`类提供了丰富的API供开发者使用,例如: 1. `charAt(int index)`:返回指定索引处的字符。 2. `concat(String ...

    老生常谈js-react组件生命周期

    React组件生命周期是指React组件从创建、挂载到卸载的一个完整过程。在这个过程中,组件会经历不同的阶段,并且会调用一系列的方法,这些方法统称为生命周期方法。理解组件的生命周期对于构建高效、可维护的React...

    老生常谈java中的数组初始化

    String[] str1 = new String[]{"A", "B", "C"}; ``` 或者简化形式: ```java String str2[] = {"A", "B", "C"}; String str3 = {"A", "B", "C"}; // 这种写法只适用于单行声明,且从Java 5开始引入 ``` 在静态初始...

    单元测试进行曲

    单元测试进行曲单元测试又是老生常谈-'单元测试',说实话自己在单元测试上是'语言上的巨人,行动上的矮子',属于那种说的比做的多的人^_^。不过也不能说什么也没做。记得去年年末的时候自己还设计并实现过一个简单的...

    老生常谈java中的fail-fast机制

    public static void main(String[] args) { for (int i = 0; i ; i++) { list.add(i); } new ThreadOne().start(); new ThreadTwo().start(); } } ``` 在这个示例中,我们创建了两个线程,ThreadOne用于遍历...

    老生常谈java中的Future模式

    老生常谈java中的Future模式 在 Java 中,Future 模式是一种常用的设计模式,用于处理并发编程中的多线程问题。在这个模式中,线程 A 需要等待线程 B 的结果,但线程 A 不需要一直等待线程 B,可以先拿到一个未来的...

    老生常谈PHP位运算的用途

    位运算是计算机科学中的基础概念之一,它直接操作整数的二进制位。... 在用户权限管理中,位运算被广泛应用于权限的设置与检查。通过位运算符,每个权限都可以对应到一个特定的二进制位,从而通过简单的位运算即可快速...

    老生常谈JavaScript中的this关键字

    相对于很多其他的面向对象语言来说,this代表的就是当前对象。例如Java中的this就是编译...Person p = new Person("zmt",30); System.out.println(p.name); } } class Person{ String name; int age; Person(String n

    老生常谈js动态添加事件--- 事件委托

    在上面的示例代码中,`.on()`方法的第一个参数是事件类型(如'click'),第二个参数是选择器(如'li[class=aaa]'),用于指定哪些子元素应当触发这个事件处理器,第三个参数是一个函数,定义了当事件发生时的具体...

    老生常谈Java网络编程TCP通信(必看篇)

    * String getCanonicalHostName() 获取此 IP 地址的完全限定域名 * String getHostAddress() 返回 IP 地址字符串 获取本地地址和端口号: ``` public void testSocket() throws Exception{ Socket socket=new ...

    在nuxt中使用路由重定向的实例

    我们都知道,在写SPA的时候,我们可以通过配置vue-router来实现路由的重定向。 官方文档(以及ts类型)的定义中给出了这一...这些都是老生常谈了。 然而,到了SSR的环境下,如果使用nuxt,因为nuxt采用了约定大于配置的

    老生常谈Bootstrap媒体对象

    Bootstrap媒体对象是网页布局中一个常用的工具,尤其在创建响应式设计时,它能帮助开发者轻松实现图文混排效果。媒体对象通常用于构建各种类型的组件,例如评论、博客文章、用户资料等,使得图片和文字内容能够以...

Global site tag (gtag.js) - Google Analytics