9
public static final String Test = "ABC";
public static String Test = "ABC";

请说明java中“final static String”和“static String”的区别。除了最后一个不能改变,还有什么区别?谢谢。在多线程和继承等更复杂的情况下,什么都没有改变?

4

14 回答 14

9

虽然以下描述取自 Android 文档,但可能有助于解决这个 Java 标记问题。

考虑类顶部的以下声明:

static int intVal = 42;
static String strVal = "Hello, world!";

编译器生成一个类初始化方法,称为 ,该方法在第一次使用该类时执行。该方法将值 42 存储到 intVal 中,并从类文件字符串常量表中提取 strVal 的引用。稍后引用这些值时,将通过字段查找来访问它们。

我们可以使用“final”关键字改进问题:

static final int intVal = 42;
static final String strVal = "Hello, world!";

该类不再需要方法,因为常量进入 dex 文件中的静态字段初始值设定项。引用 intVal 的代码将直接使用整数值 42,而对 strVal 的访问将使用相对便宜的“字符串常量”指令而不是字段查找。

笔记:

此优化仅适用于原始类型和字符串常量,而不适用于任意引用类型。不过,尽可能将常量声明为 static final 是一种很好的做法。

希望这会清楚。

UseFinal中的更多详细信息

于 2013-01-07T05:27:15.977 回答
7

当涉及到变量

  • final Static String- 常量,它是类变量
  • static String- 类变量而不是常量
于 2013-01-07T04:58:13.567 回答
3

这里还有更多

static final String s1;
static String s2;

第 1 行不编译,第 2 行编译

原始类型还有更多。

final int x = 1;

void x() {
    int y = x + 1;
}

字节码

ICONST_2
ISTORE 1

这意味着int y = 2因为 x 是一个常数(尽管它不是静态的)

如果我们改变

int x = 1;

字节码

ALOAD 0
GETFIELD Test1.x : I
ICONST_1
IADD
ISTORE 1

JVM 读取 x 并计算 y

于 2013-01-07T05:02:06.727 回答
1

根据维基

如果该变量是一个引用,这意味着该变量不能被重新绑定以引用另一个对象。但是它引用的对象仍然是可变的,如果它最初是可变的。

但是,由于从开始String不可变的,因此在这种情况下差异是无关紧要的,它只是一个无论如何都不能修改的变量

于 2013-01-07T04:59:46.347 回答
1

你自己说的:最后一个不能分配。据我所知,final修饰符提供了除此之外的其他行为。我能想到的唯一一件事Testpublic,编译staticfinal会自动替换Test代码中所有出现"ABC"的. 基本上,final 可以防止将 String 分配给不同的引用,仅此而已。

于 2013-01-07T05:01:28.630 回答
1

一个final类不能被子类化。这就像sealedC# 中的类。

方法final不能被覆盖。

一个final字段只能被初始化/分配一次,就像一个常量,但在编译时可能不一定知道。

static成员在类的所有实例上共享。

所以,static final通常是为了你永远不会再改变的东西,但不一定在编译时硬编码。

于 2013-01-07T05:06:31.017 回答
1

将 java 变量声明为 static final 时,编译的 java 类会提高性能。

检查这个

于 2013-01-07T05:09:03.500 回答
0

您不能更改最终的参考如下

public static final String Test1 = "ABC";
public static String Test2 = "ABC";
public static void testFinal()
{
    Test2 = Test1; //ok
    Test1 = Test2; //fail
}
于 2013-01-07T05:17:03.397 回答
0

我认为在字符串的情况下它们之间没有其他区别。

在多线程的情况下,建议我们应该尝试使对象不可变,这样就不会有对象状态发生不希望的状态更改的风险(由于不正确的同步或避免同步开销)。

final如果使用得当,关键字(在类、字段、方法等各个地方)有助于实现不变性,但Strings 默认情况下是不可变的。

在继承的情况下,最终方法不能被覆盖,但这里又不是这种情况。

于 2013-01-07T05:45:04.527 回答
0

final 静态字符串 - 常量,它是类变量,可以从任何类访问,但不能更改静态字符串 - 类变量,而不是常量,可以从任何类访问和更改

于 2013-01-07T06:01:32.363 回答
0

我认为第一个语句通常用于定义一个字符串常量。并且常量变量名建议使用“TEST”而不是“Test”。

public static final String TEST = "ABC";

第二个语句很少使用是有充分理由的。它可能会导致多线程上下文中的并发问题。我们可以在我们的类中有私有实例字符串字段:

private String test = "ABC";

希望这可以帮助!

于 2013-01-07T06:03:46.030 回答
0

final变量是实例变量,初始化后其值不能改变。

但是静态变量属于一个类。这将在所有实例之间共享。因此,当您更改实例中静态变量的值时,它会反映在所有实例中。

于 2013-01-07T05:03:09.353 回答
0

字符串既可以声明为静态的,也可以声明为最终的。使用这两个访问说明符声明字符串的优点如下所述。

优点包括 final 和 static 的影响。

  1. 不能重新分配声明为 final 的字符串。字符串作为常量工作。

  2. 可以在没有对象或类名的帮助下调用声明为静态的字符串。

  3. 静态变量不维护封装。将静态变量声明为 final,没有对象可以更改该值但可以访问它。

    public class Demo {
    
    static final String str = "Hello";
    
    public static void main(String args[]) {
    // str = "world"; // gives error
    System.out.println(str); // called without the help of an object
    System.out.println(Demo.str);// called with class name
    
    }
    }
    

main() 方法中的第一条语句给出了错误,因为字符串 str 被声明为 final。

以下语句引发编译错误,因为字符串 str 被声明为 final。

Demo d1 = new Demo();
d1.str =  "World";

实时示例

static final String truth = "太阳从东方升起";

于 2013-01-07T05:28:20.497 回答
0

干得好:

1) final static String: 当你说 final 它是一个常数并且你不能在整个程序中改变它的值。它不是一个变量,你不能改变它的值。在 Java 中,我们使用 final 关键字来声明常量。在声明常量时,我​​们应该在所有大写字母后面加上下划线来分隔单词。例如:MAX_INPUT_TIME、CONNECTION_POOL_SIZE、MAX_USER 等。

2)static String:您可以将静态用于类的成员变量,而不能用于局部变量。静态变量是静态的,即使不创建类的实例也可以访问。因此,您可以通过object.<static_variable_name>或使用它们ClassName.<static_variable_name>。它们是可访问的,并且对于类的所有实例都具有相同的值。

例如:

Class A {
  static int counter;  // it will be default to 0
}

现在在使用这个类时:

System.out.println(A.counter);  // output: 0
A.counter++;
System.out.println(A.counter);  // output: 1
// Declare an instance of class A
A o1 = new A();
o1.counter++;
System.out.println(o1.counter);  // output: 1
// Declare another instance of class A
A o2 = new A();
System.out.println(o1.counter);  // output: 1  
# You still get it one and not 0, if it was non-static you would get it as 0;

例如,在这里,您可以使用静态变量来跟踪通过在构造函数本身中放置计数器增量而创建的对象数量。

于 2013-01-07T05:32:18.017 回答