菜菜

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

posted on 2017-05-14 17:56  好吧,就是菜菜  阅读(269)  评论(0编辑  收藏  举报