РЕДАКТИРОВАТЬ: я предполагаю, что вы знаете, что вы сравниваете ссылки, а не содержимое строк. Если нет, то s3.equals(s5)
- это то, что вы ищете (как уже упоминалось).
s3
оптимизируется компилятором до "hellohello1"
, который также используется для s4
. Я весьма удивлен, что компилятор не настолько умен, чтобы делать то же самое для s5
. Какую версию JDK вы используете? . Эта оптимизация допускается только для константных выражений (см. 15.28 спецификации языка Java ). Другими словами, любое присвоение неконечной переменной отрицает возможность последующей оптимизации.
Вот вывод javap -c -l
простого класса, который упаковывает ваш код в основной метод (не то, чтобы кто-то об этом просил, но мне самому любопытно). Итак, давайте посмотрим, что происходит:
public static void main(java.lang.String[]);
Code:
0: ldc #16; //String hello
2: astore_1
3: ldc #18; //String hello1
5: astore_2
6: ldc #20; //String hellohello1
8: astore_3
9: ldc #20; //String hellohello1
11: astore 4
13: new #22; //class java/lang/StringBuilder
16: dup
17: aload_1
18: invokestatic #24; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
21: invokespecial #30; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
24: aload_2
25: invokevirtual #33; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #37; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore 5
33: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
36: aload_3
37: aload 4
39: if_acmpne 46
42: iconst_1
43: goto 47
46: iconst_0
47: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
50: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
53: aload_3
54: aload 5
56: if_acmpne 63
59: iconst_1
60: goto 64
63: iconst_0
64: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
67: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
70: aload 4
72: aload 5
74: if_acmpne 81
77: iconst_1
78: goto 82
81: iconst_0
82: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
85: return
LocalVariableTable:
Start Length Slot Name Signature
0 86 0 args [Ljava/lang/String;
3 83 1 s1 Ljava/lang/String;
6 80 2 s2 Ljava/lang/String;
9 77 3 s3 Ljava/lang/String;
13 73 4 s4 Ljava/lang/String;
33 53 5 s5 Ljava/lang/String;
}
У меня нет опыта чтения байт-кода, но я попробую :)) 1020 *
- числа, начинающиеся с # (например, # 16), являются ссылками на постоянный пул. Содержимое всегда добавляется как комментарий к этой строке
ldc #16
, за которым следует astore_1
означает «загрузить константу # 16 и сохранить ее в слоте 1». Как вы можете видеть, это делается 4 раза в начале для слотов 1 - 4, что переводит в s1, s2, s3 и s4 (см. LocalVariableTable).
- для s5, не вдаваясь в подробности, очевидно, есть StringBuilder и загрузка слота 1 (
aload_1
) и слота 2 (aload_2
) перед сохранением результата в слоте 5 (astore 5
).