2011-11-04 84 views
38

通常,最终静态成员,特别是变量(或静态最后,当然,它们可以以任意顺序使用,而不会重叠含义)广泛用于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

'static'字段只能属于一个Class,因此编译器错误。 'final'意味着变量在第一次初始化后永远不能被改变。 – brc

+0

@EJP啊,也许我错了。没关系! – bdonlan

+0

@bdonlan事实上,接口变量在Effective Java中被提及为反模式。 –

回答

115

您正在使许多不同概念的巨大组合。即使是标题中的问题也不符合正文中的问题。

不管怎么说,这些都是你混淆的概念:

  • 变量
  • 最终变量
  • 领域
  • 最终场
  • 静态字段
  • 最终静态字段

关键字static仅适用于字段,但是在显示的代码中,您试图在函数内部使用它,您无法声明字段(字段是类的成员;变量在方法中声明)。

让我们尝试快速描述它们。在方法声明,并用作某种可变本地存储int x; x = 5; x++)在方法也宣告

  • 最后的变量,并且被用作

    1. 变量不可变的本地存储(final int y; y = 0; y++; // won't compile)。它们对于捕捉错误有用,因为有人会尝试修改不应该修改的内容。我个人使我的大部分本地变量和方法参数final。而且,当你从内部的匿名类中引用它们时,它们是必需的。在一些编程语言中,唯一一种变量是不可变变量(在其他语言中,“默认”类型的变量是不可变变量) - 作为练习,试图找出如何编写循环来运行在初始化后不允许更改任何内容时指定的次数! (例如,尝试用最终变量解决fizzbuzz!)。

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

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

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

    5. 最终静态字段全局常量class MyConstants { public static final double PI = 3.1415926535897932384626433; })。

    还有许多其他的细微特征(如:编译器是免费更换引用到最后的静态字段直接它们的值,这使得在这些领域反射无用的;最后的字段实际上可能与反思修改,但这是非常容易出错的,等等),但是我想说在挖掘之前还有很长的路要走。

    最后,也有可能与领域中使用,如transientvolatile其他关键字和访问级别(publicprotectedprivate)。但这是另一个问题(事实上,如果你想问他们,还有很多其他问题,我会说)。

  • +5

    +1,清晰且很好的解释! –

    +0

    @Bruno - FizzBu​​zz是如何使用final变量和final字段实现的。你可以解释吗。谢谢。 – rtindru

    +0

    @rtindru,提示:考虑一个类,该类有一个递归地创建同一个类的新实例并递归调用相同方法的方法。非常人造,但可行。 –

    25

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

    最终其他条款,是一个常数(如在C)。您可以在方法内以及课堂级别都有最终变量。如果你把最后的静态变成“一个不变的类成员”

    +6

    +1,简而言之,好的解释 – Naved

    +0

    @downvoters请解释 – NavSoft

    +1

    *你可以在方法内有最后一个字段* - 一个字段不能在方法内声明。这将被称为最终变量。 –

    1

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

    如果您希望为static,请使用final static。如果您不希望它是static,请使用final(非静态)。

    静态变量或最终静态变量永远不能被声明 既不内部的静态方法,也没有一个实例 方法内的方法内。为什么?

    设计决定。没有问詹姆斯戈斯林就没有办法回答这个问题。

    下面的代码段相应地,将不被编译和 编译时间错误会被编译器发出的,如果试图是 由编译它。

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

    1

    final关键字只是意味着“这个不能改变”。它可以与方法中的字段和变量一起使用。当变量被声明为final时,尝试更改该变量将导致编译时错误.For例如,如果我将变量声明为final int x = 12;试图增加x就是(++ x)会产生一个错误。简言之,final是一个常量。 另一方面,静态只能应用于字段,而不能应用于方法。最终静态的字段只有一个存储区。最终显示它是一个常量(不能更改),静态显示它只有一个。

    0

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