Java中静态变量和最终静态变量之间的区别

时间:2011-11-04 05:30:19

标签: java

通常,最终的静态成员,尤其是变量(或者当然,静态最终,它们可以按任意顺序使用而不重叠含义)广泛用于Java中的接口,以定义协议行为实现类,它意味着实现(继承)接口的类必须包含该接口的所有成员。


我无法区分最终最终静态成员。最终的静态成员是一个声明为final或其他东西的静态成员?具体情况应该在哪些特定情况下使用?


静态变量或最终静态变量永远不能在静态方法内部和实例方法内部的方法内声明。为什么呢?

如果尝试编译它,将不会编译以下代码段,并且编译器将发出编译时错误。

public static void main(String args[])
{
    final int a=0;  //ok

    int b=1;  //ok

    static int c=2;  //wrong

    final static int x=0;  //wrong
}

7 个答案:

答案 0 :(得分:118)

你正在混合许多不同的概念。甚至标题中的问题也与正文中的问题不符。

无论如何,这些是你正在混淆的概念:

  • 变量
  • 最终变量
  • 字段
  • 最终字段
  • 静态字段
  • 最终静态字段

关键字static仅对字段有意义,但在您展示的代码中,您尝试在函数内使用它,您无法声明字段(字段是类的成员;变量在方法中声明)

让我们试着快速描述它们。

  1. 变量在方法中声明,并用作某种可变本地存储int x; x = 5; x++

  2. 最终变量也在方法中声明,并用作不可变本地存储final int y; y = 0; y++; // won't compile)。它们可用于捕获有人试图修改不应修改的内容的错误。我亲自制作了大部分局部变量和方法参数final。此外,当您从内部匿名类引用它们时,它们是必需的。在某些编程语言中,唯一的变量是不可变变量(在其他语言中,“默认”类型的变量是不可变变量) - 作为练习,尝试弄清楚如何编写一个循环来运行初始化后不允许更改任何内容时指定的次数! (例如,尝试用最终变量来解决 fizzbuzz !)。

  3. 字段定义对象的可变状态,并在类(class x { int myField; })中声明。

  4. 最终字段定义对象的不可变状态,在类中声明,必须在构造函数完成之前初始化(class x { final int myField = 5; })。它们无法修改。它们在执行多线程时非常有用,因为它们具有与线程间共享对象相关的特殊属性(如果在构造函数完成后共享对象,则保证每个线程都能看到对象的最终字段的正确初始化值,并且即使它与数据竞争共享)。如果你想要另一个练习,尝试仅使用final字段再次解决 fizzbuzz ,没有其他字段,没有任何变量或方法参数(显然,你可以在构造函数中声明参数,但这就是全部! )。

  5. 静态字段在所有类的所有实例之间共享。您可以将它们视为某种全局可变存储(class x { static int globalField = 5; })。最简单(通常是无用的)示例是计算对象的实例(即class x { static int count = 0; x() { count++; } },这里构造函数在每次调用时递增计数,即每次创建{{1}的实例时与x)。请注意,与最终字段不同,它们本身并不是线程安全的;换句话说,如果你从不同的线程实例化,你肯定会得到错误的new x()实例和上面的代码;为了使它正确,你必须添加一些同步机制或为此目的使用一些专门的类,但这是另一个问题(实际上,它可能是整本书的主题)。

  6. 最终静态字段全局常量x)。

  7. 还有许多其他微妙的特征(例如:编译器可以直接将对最终静态字段的引用替换为它们的值,这使得反射在这些字段上无用;最终字段实际上可能会被反射修改,但这是非常错误的倾向;等等),但我要说你在进一步挖掘之前还有很长的路要走。

    最后,还有其他可能与字段一起使用的关键字,例如class MyConstants { public static final double PI = 3.1415926535897932384626433; }transient和访问权限级别volatilepublic,{{1} })。但这是另一个问题(实际上,如果您想询问它们,还有许多其他问题,我会说)。

答案 1 :(得分:26)

静态成员是可以在不创建对象的情况下访问的成员。这意味着那些是类成员,与任何实例无关。因此不能在方法中定义。

在其他方面,

最终是一个常数(如在C中)。您可以在方法内部以及类级别中拥有最终变量。如果你把final作为静态变成“一个恒定的类成员”

答案 2 :(得分:1)

  

我无法区分最终和最终的静态成员。   最终的静态成员是声明的静态成员   作为决赛或其他什么?他们应该在哪种特殊情况下   具体使用?

如果希望final static static,请使用final。如果您不希望static {{1}},请使用{{1}}(非静态)。

  

永远不能声明静态变量或最终静态变量   在方法内部既不在静态方法内也不在实例内部   方法。为什么呢?

设计决定。如果不问James Gosling,就没有办法回答这个问题。

  

相应的以下代码段,将不会编译和   如果尝试,编译时错误将由编译器发出   编译它。

因为它违反了您刚才描述的规则。

答案 3 :(得分:1)

final关键字仅表示“无法更改”。它可以与方法中的字段和变量一起使用。当变量声明为final时,尝试更改变量将导致编译时错误。例如如果我将变量声明为final int x = 12;试图增加x即(++ x)将产生错误。简而言之,基元最终使值成为常数。 另一方面,静态只能应用于字段而不能应用于方法。最终静态的字段只有一个存储空间。最终显示它是一个常量(不能更改),静态显示它只有一个。 / p>

答案 4 :(得分:1)

在Java中,静态变量是属于类而不是类的对象,同一个类的不同实例将包含相同的静态变量值。

final 变量是一个在初始化之后,在类的实例化(创建一个对象)之后不能在程序中改变的变量。但是,如果在创建同一类的另一个对象后传递不同的值,则这与对象不同。

final static 表示变量属于类,并且一旦初始化就不能更改。因此,可以在同一类的不同实例中访问相同的值。

答案 5 :(得分:0)

你不能在静态块中声明静态字段,静态字段只能属于一个类,因此编译错误。

答案 6 :(得分:0)

只需在@Bruno Reis的答案中添加一些次要信息,我就试图完成答案,因为他谈到了在构造函数结束之前初始化最终字段的重要条件,最终静态字段也必须在静态块之前进行初始化执行结束。