“final static String”和“static String”之间的区别?

时间:2013-01-07 04:56:24

标签: java

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

请在java中显示“final static String”和“static String”之间的区别。 除了最后一个不能改变,其他差异是什么?谢谢。 在多线程和继承等更复杂的情况下,什么都没有改变?

14 个答案:

答案 0 :(得分:9)

虽然下面的描述取自Android doc,但可能有助于此Java标记的问题。

在课程顶部考虑以下声明:

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

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

我们可以使用“最终”关键字来改善问题:

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

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

注意:

  

此优化仅适用于基本类型和字符串   常量,而不是任意引用类型。不过,这是一个很好的做法   尽可能声明常量静态final。

希望这会清楚。

UseFinal

的更多详情

答案 1 :(得分:7)

谈到变量

  • final Static String - 常量,它是类变量
  • static String - 类变量而不是常量

答案 2 :(得分: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

答案 3 :(得分:1)

根据wiki

  

如果变量是引用,则意味着无法重新绑定变量以引用另一个对象。但它引用的对象仍然是可变的,如果它最初是可变的。

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

答案 4 :(得分:1)

你自己说:最后一个不能分配。据我所知,final修饰符提供了除此之外的其他行为。我唯一能想到的是,Testpublicstaticfinal,编译器会自动替换您Test中出现的所有"ABC"代码并用String Literal {{1}}替换它,虽然String将被实现,但它不会对代码产生任何影响。基本上,final会阻止将String分配给不同的引用,即all。

答案 5 :(得分:1)

final类无法进行子类化。它类似于C#中的sealed类。

无法覆盖final方法。

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

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

因此,static final通常用于您永远不会再次更改的内容,但不一定在编译时进行硬编码。

答案 6 :(得分:1)

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

Check This

答案 7 :(得分:0)

最终变量是实例变量,其值在初始化后无法更改。

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

答案 8 :(得分:0)

您无法更改最终的参考资料,如下所示

public static final String Test1 = "ABC";
public static String Test2 = "ABC";
public static void testFinal()
{
    Test2 = Test1; //ok
    Test1 = Test2; //fail
}

答案 9 :(得分:0)

字符串可以声明为static和final。下面将叙述使用两个访问说明符声明字符串的优点。

优点包括最终和静态的影响。

  1. 无法重新分配声明为final的字符串。该字符串用作常量。

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

  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
    
    }
    }
    
  4. main()方法中的第一个语句给出错误,因为字符串str被声明为final。

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

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

    实时示例

    static final String truth =“太阳升起在东方”;

答案 10 :(得分:0)

你走了:

1)final static String:当你说最终它是一个常数,你不能在整个程序中改变它的价值。它不是变量,你不能改变它的价值。在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;

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

答案 11 :(得分:0)

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

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

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

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

答案 12 :(得分:0)

final Static String - 常量,它是类variableit可以访问但不能从任何类更改 static String - 类变量而不是常量,可以从任何类访问和更改

答案 13 :(得分:0)

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

public static final String TEST = "ABC";

第二种说法很少被用于充分理由。它可能会导致多线程上下文中的并发问题。我们可以在类中使用私有实例String字段:

private String test = "ABC";

希望这有帮助!