Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这会根据最终变量给出不同的结果_Java - Fatal编程技术网

Java 为什么这会根据最终变量给出不同的结果

Java 为什么这会根据最终变量给出不同的结果,java,Java,输出:假真 如果我们看到Ref.变量“b”指向“abcd”字符串对象,Ref.变量“c”也指向同一字符串对象,即“abcd”,但当我们使用==(双相等运算符)运算符检查相等时,它会在第10行打印false。但如果我们将Ref.变量“a”作为最终变量,那么它将在第10行打印true 所以我有点困惑。有人能告诉我它背后发生了什么吗?使afinal允许编译器解释b=a+“d”完全类似于c=“abc”+“d”,因为a的值不能更改 在这种情况下,编译器可以很容易地看到a没有被更改,但是javac没有进行非

输出:

如果我们看到Ref.变量“b”指向“abcd”字符串对象,Ref.变量“c”也指向同一字符串对象,即“abcd”,但当我们使用==(双相等运算符)运算符检查相等时,它会在第10行打印false。但如果我们将Ref.变量“a”作为最终变量,那么它将在第10行打印true


所以我有点困惑。有人能告诉我它背后发生了什么吗?

使
a
final允许编译器解释
b=a+“d”完全类似于
c=“abc”+“d”,因为
a
的值不能更改


在这种情况下,编译器可以很容易地看到
a
没有被更改,但是
javac
没有进行非常复杂的代码分析,因此您需要通过将
a
设置为final来帮助它,以便编译器在编译时进行优化。

对于值得更改的内容,这里是字节码的比较。左侧显示编译结果,不使用
final
修饰符,右侧显示使用
final
修饰符:

public class Example {

public static void main(String[] args) {

    String a = "abc"; // Line 5
    String b = a + "d"; // Line 6
    String c = "abc"+ "d"; // Line 7
    String d = "abcd"; //Line 8

    System.out.println(b==c); //Line 10 
    System.out.println(c==d); //Line 11
}
}
我们可以看到字节码基本上是相同的,除了开头:在这里,没有final
修饰符的版本加载字符串
“abc”
“d”
,并使用一些
StringBuilder#append
调用来组装它们


因此,这基本上证实了什么:如果添加了
final
修饰符,编译器可以预先将字符串组装成
“abcd”

正如我们所知,一旦创建字符串对象,我们就不能更改它,因为本质上字符串在java中是不可变的。那么为什么我们需要将字符串对象作为final@GauravPriyadarshi
String
对象是不可变的,但是变量
a
可以更改。对象不能是final,引用它们的变量可以是final。
 0: ldc           #2      // String abc    |     0: ldc           #2      // String abcd
 2: astore_1                               |     2: astore_2
 3: new           #3      // class ...     |
 6: dup                                    |
 7: invokespecial #4      // Method ...    |
10: aload_1                                |
11: invokevirtual #5      // Method ...    |
14: ldc           #6      // String d      |
16: invokevirtual #5      // Method ...    |
19: invokevirtual #7      // Method ...    |
22: astore_2                               |
23: ldc           #8      // String abcd   |     3: ldc           #2      // String abcd
25: astore_3                               |     5: astore_3
26: ldc           #8      // String abcd   |     6: ldc           #2      // String abcd
28: astore        4                        |     8: astore        4
30: getstatic     #9      // Field ...     |    10: getstatic     #3      // Field ...
33: aload_2                                |    13: aload_2
34: aload_3                                |    14: aload_3
35: if_acmpne     42                       |    15: if_acmpne     22
38: iconst_1                               |    18: iconst_1
39: goto          43                       |    19: goto          23
42: iconst_0                               |    22: iconst_0
43: invokevirtual #10     // Method ...    |    23: invokevirtual #4      // Method ...
46: getstatic     #9      // Field ...     |    26: getstatic     #3      // Field ...
49: aload_3                                |    29: aload_3
50: aload         4                        |    30: aload         4
52: if_acmpne     59                       |    32: if_acmpne     39
55: iconst_1                               |    35: iconst_1
56: goto          60                       |    36: goto          40
59: iconst_0                               |    39: iconst_0
60: invokevirtual #10     // Method ...    |    40: invokevirtual #4      // Method ...
63: return                                 |    43: return