• 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循环

  • 相关阅读:
    iOS加载HTML, CSS代码
    iOS搜索指定字符在字符串中的位置
    【解决方法】You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE)
    刷新指定行或区 cell
    支付宝获取私钥和公钥
    什么是Git?
    第三方库AFNetworking 3.1.0的简单使用
    转:KVC与KVO机制
    转:常用的iOS开源库和第三方组件
    转:setValue和setObject的区别
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/6853162.html
Copyright © 2020-2023  润新知