這個太簡單了,我也不會

weixin_33866037發表於2018-03-19

假設 userId 是 int 型,想 要一個 String 型別的 userId,String.valueOf(userId) 更好還是 userId + "" 更好。

最近有同學問了這樣一個問題,咋一看似乎只是一個打碼風格問題,但是如果非讓你選一個好的怎麼辦呢,還是得測試一下呀。
簡單的模擬一下場景:

//寫法一:
public class Test{
        public static void main(String[] args){
                int i=0;
                System.out.println(i + "");
        }
}
//寫法二:
public class Test2{
        public static void main(String[] args){
                int i=1;
                System.out.println(String.valueOf(1));
        }
}

單從寫法上我是更傾向於第二種寫法的,雖然多寫幾個字母但我認為這樣更符合編碼的習慣,畢竟➕一個空字元總感覺多了一些什麼奇怪的東西。
但是這樣說很蒼白無力啊,誰也說服不了,為了證明我的喜好更好,來看看位元組碼。

zeal-pc:test zeal$ javap -c Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       5: new           #3                  // class java/lang/StringBuilder
       8: dup
       9: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      12: iload_1
      13: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      16: ldc           #6                  // String
      18: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      24: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      27: return
}

zeal-pc:test zeal$ javap -c Test2
Compiled from "Test2.java"
public class Test2 {
  public Test2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       5: iconst_1
       6: invokestatic  #3                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
       9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      12: return
}

嗯,第一個比第二個長,我贏了。
還有就是,“+”在編譯期會被用StringBuilder來實現這個想必大家都是知道的,從第一個可以看到程式碼執行了兩次append方法,而第二個只是執行了一個valueOf方法。同時對比StringBuilder和String的原始碼可以發現append裡面執行了一次getChars方法(ensureCapacityInternal陣列拷貝這種情況並不會觸發;append int是讀表操作,append string是陣列拷貝),valueOf裡只是執行了一次getChars(讀表)方法。

總結一下String.valueOf 速度更快,寫法更優雅。

然而寫法一在現在的多核多G機器上也並不會有啥影響。

相關文章