了解 java 个最终变量

Understanding java final variables

你能帮我理解如果在字符串连接中使用最终变量会发生什么吗? 这是一个认证问题,所以不是关于如何比较 string

的问题
String var1 = "varan";       
String an = "an";
final String an2 = "an";
System.out.println(var1 == ("var"+an));       
System.out.println(var1 == ("var"+an2));

输出:

false
true

TL;DR

因为"var"+an是在运行时新创建的不同的StringObject"var"+an2是编译时常量实习,并引用 var1 引用的同一地址。


考虑以下与您的代码类似的示例。

public class TestString {

    public static void main(String[] args) {
        String Whosebug = "Whosebug";
        String overflow = "Overflow";

        final String overflowFinal = "Overflow";

        if (overflow == overflowFinal) {
            System.out.println("Both overflows are same!");
        }

        if (Whosebug == ("stack" + overflow)) {
            System.out.println("Stack and overflow have same reference !");
        }

        if (Whosebug == ("stack" + overflowFinal)) {
            System.out.println("Stack and overflowFinal have same reference !");
        }
    }

}

它将给出以下输出:

Both overflows are same!
Stack and overflowFinal have same reference !

首先请注意,== 比较的是 Strings 的引用,而不是实际值。

JLS 15.18.1 表示,

The result of string concatenation is a reference to a String object that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string.

The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).

所以,从上面的陈述我们可以说 "stack" + overflow 将类似于 String newString = new String("Whosebug");(在内部 编译器 将使用 StringBuilder 来执行此操作连接)。

对于 final String JLS 4.12.4 个州,

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

and so §15.28 says

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

...

  • The additive operators + and -

...

Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.

现在,上面的语句说如果我们将 String 声明为 final,它最终会变成 常量表达式

请注意 String 字面量也被保留。

Interned String 表示如果您正在创建具有相同内容的 String 和一个 String 检查 .equals() method) 已经存在于内存中,那么它不会创建新的 String 但它会引用 same 内存位置。

例如,

String a = "test";//String literals
String b = "test";
System.out.println("Is a & b interned ? :"+(a == b));

输出:

Is a & b interned ? : true