zoukankan      html  css  js  c++  java
  • Java面试题之最扯淡的String


    SB里面的toString方法如下,为什么需要这个,查看JVM虚拟机指令用,+号会变成new SB()的,然后调用toString方法
      public String toString() {
            // Create a copy, don't share the array
            return new String(value, 0, count);
        }
    

      


    public class ThreadException { public static void main(String[] args) {
            没加final的代码 String hello = "hello"; String hel = "hel"; String lo = "lo"; System.out.println(hello == "hel" + "lo"); System.out.println(hello == "hel" + lo); } }
    没加final的代码反编译回来后的代码
    import java.io.PrintStream;
    
    public class ThreadException
    {
    public static void main(String[] paramArrayOfString)
    {
    String str1 = "hello";
    String str2 = "hel";
    String str3 = "lo";
    System.out.println(str1 == "hello");
    System.out.println(str1 == "hel" + str3);
    }
    }
    没加final的虚拟机执行的指令集如下
    public static void main(java.lang.String[]);
    Code:
    0: ldc #2 // String hello
    2: astore_1
    3: ldc #3 // String hel
    5: astore_2
    6: ldc #4 // String lo
    8: astore_3   //将操作数栈顶的值保存在本地变量表,变量地址放本地变量表3位置  
    9: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
    12: aload_1
    13: ldc #2 // String hello
    15: if_acmpne 22
    18: iconst_1
    19: goto 23
    22: iconst_0
    23: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
    26: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
    29: aload_1
    30: new #7 // class java/lang/StringBuilder
    33: dup
    34: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
    37: ldc #3 // String hel    //这句加载常量到操作数栈  hel
    39: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    42: aload_3          //加载一个本地变量到操作数栈,从本地变量表3这个位置,将里面的值放到操作数栈上去
    43: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    46: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;//SB.tostring
    49: if_acmpne 56
    52: iconst_1
    53: goto 57
    56: iconst_0
    57: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
    60: return

      再看下面这个,多加了一个final

    加了final的代码
    public class ThreadException { public static void main(String[] args) { String hello = "hello"; String hel = "hel"; final String lo = "lo"; System.out.println(hello == "hel" + "lo");//true System.out.println(hello == "hel" + lo);//true } }
    加了final后反编译回来的代码
    import java.io.PrintStream; public class ThreadException { public static void main(String[] paramArrayOfString) { String str4 = "hello"; String str5 = "hel"; System.out.println(str4 == "hello"); System.out.println(str4 == "hello"); } }

    看下加了final的虚拟机代码 
    public static void main(java.lang.String[]);
    Code:
    0: ldc #2 // String hello   //加载常量到操作数栈,常量是hello
    2: astore_1
    3: ldc #3 // String hel
    5: astore_2
    6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
    9: aload_1
    10: ldc #2 // String hello
    12: if_acmpne 19
    15: iconst_1
    16: goto 20
    19: iconst_0
    20: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
    23: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
    26: aload_1
    27: ldc #2 // String hello  加载常量
    29: if_acmpne 36    比较
    32: iconst_1
    33: goto 37
    36: iconst_0
    37: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
    40: return
    }

      再来看这段代码

    public class ThreadException
    {
    
      加了final public static void main(String[] args) { String s = new String("abc"); final String s1 = "abc"; String s2 = new String("abc"); final String s3 = "abc"; System.out.println(s == s.intern()); System.out.println(s1 == s2.intern()); System.out.println(s2.intern() == s2.intern()); System.out.println(s3 == s1); } }
    加了final反编译回来的代码
    
    import java.io.PrintStream;
    
    public class ThreadException
    {
      public static void main(String[] paramArrayOfString)
      {
        String str1 = new String("abc");
    
        String str2 = new String("abc");
    
        System.out.println(str1 == str1.intern());
        System.out.println("abc" == str2.intern());
        System.out.println(str2.intern() == str2.intern());
    //这段是不是很惊讶
        System.out.println(true);
      }
    }
    是不是很扯淡?

      再看没加final的

    public class ThreadException
    {
    
    	public static void main(String[] args)
    	{
      没加final的代码
    		String s = new String("abc");
    		 String s1 = "abc";
    		String s2 = new String("abc");
    		 String s3 = "abc";
    		System.out.println(s == s.intern());
    		System.out.println(s1 == s2.intern());
    		System.out.println(s2.intern() == s2.intern());
    		System.out.println(s3 == s1);
    	}
    }
    没加final反编译后的代码
    
    
    import java.io.PrintStream;
    
    public class ThreadException
    {
      public static void main(String[] paramArrayOfString)
      {
        String str1 = new String("abc");
        String str2 = "abc";
        String str3 = new String("abc");
        String str4 = "abc";
        System.out.println(str1 == str1.intern());
        System.out.println(str2 == str3.intern());
        System.out.println(str3.intern() == str3.intern());
        System.out.println(str4 == str2);
      }
    }

      是不是都感觉很扯淡,还是C++ Primer里面那句话,对于字面量字符串的处理,有些编译器会保存一个,有些会保存多个副本,所以,

         想判断String字面量是否相等,老老实实的for循环

  • 相关阅读:
    转载CSDN(educast):c# 对两个Datatable的结构相同进行合并
    .net升级到4.0之后,出现'System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its depen
    转载来自博客园(poleices):C#和JavaScript交互(asp.net前台和后台互调)总结
    Bat文件 执行MSSQL 脚本
    多功能jQuery对话框插件 jBox 2.3 正式版
    十一种Web网站程序性能测试工具介绍
    大型电子商务网站架构
    Nginx负载均衡
    文语通5.0破解版下载 有详细图解安装说明
    分享8个超棒的免费高质量图标搜索引擎
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/6853162.html
Copyright © 2011-2022 走看看