静态和最终之间的区别?


173

我一直在java中的staticfinal关键字之间感到困惑。

它们有何不同?

Answers:


237

static关键字可以在4种情况下使用

  • 静态变量
  • 静态方法
  • 静态代码块
  • 静态嵌套类

首先让我们看一下静态变量和静态方法。

静态变量

  • 它是一个属于类而不属于对象(实例)的变量。
  • 静态变量在执行开始时仅初始化一次。在初始化任何实例变量之前,将首先初始化这些变量。
  • 该类的所有实例共享的单个副本。
  • 静态变量可以通过类名直接访问,并且不需要任何对象。
  • 句法: Class.variable

静态方法

  • 它是属于类而不属于对象(实例)的方法。
  • 静态方法只能访问静态数据。除非具有/创建该类的实例,否则它无法访问非静态数据(实例变量)。
  • 静态方法只能调用其他静态方法,而不能从其调用非静态方法,除非它具有/创建了该类的实例。
  • 静态方法可以通过类名直接访问,并且不需要任何对象。
  • 句法: Class.methodName()
  • 静态方法无论如何都不能引用thissuper关键字。

静态类

Java还具有“静态嵌套类”。静态嵌套类只是一个没有隐式引用外部类实例的类。

静态嵌套类可以具有实例方法和静态方法。

Java中没有顶级静态类。

边注:

主要方法是static因为在进行任何实例化之前,应用程序必须可以访问它才能运行。

final 关键字在几种不同的上下文中用于定义一个实体,以后不能更改它。

  • 一个final类不能被子类化。这样做是出于安全和效率的考虑。因此,许多Java标准库类是final,例如java.lang.Systemjava.lang.Stringfinal类中的所有方法都是隐式的final

  • final方法不能由子类覆盖。这用于防止子类的意外行为更改可能对类的功能或一致性至关重要的方法。

  • 一个final变量只能要么通过初始化或赋值语句初始化一次。它不需要在声明时进行初始化:这称为blank final变量。必须在声明该类的每个构造函数的末尾明确分配该类的空白最终变量。类似地,必须在声明它的类的静态初始化器中明确分配一个空白的最终静态变量;否则,两种情况下都会发生编译时错误。

注意:如果变量是引用,则意味着不能将变量重新绑定为引用另一个对象。但是,如果它最初是可变的,它引用的对象仍然是可变的。

在方法的主体中定义匿名内部类final时,可以从内部类中访问在该方法范围内声明的所有变量。赋值后,最终变量的值将无法更改。


5
(我没有投票给您)一些进一步的澄清:“静态方法只能访问静态数据。它不能访问非静态数据(实例变量)”-除非它具有/创建该类的实例。“静态方法只能调用其他静态方法,而不能从中调用非静态方法。” -除非它具有/创建类的实例。
xagyg 2012年

1
在静态方法语法解释中,您认为我提到的是错误的。可能是Class.methodName()
Mdhar9e 2014年

我们也可以有静态类。纠正您的答案。谢谢:)
Madhusudan

从Java 8开始,匿名类(和lambda)可以有效地访问final变量,而没有final关键字的限制。
akhil_mittal '17

38

static表示它属于该类而不是实例,这意味着在特定Class的所有实例之间仅共享该变量/方法的一个副本。

public class MyClass {
    public static int myVariable = 0; 
}

//Now in some other code creating two instances of MyClass
//and altering the variable will affect all instances

MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass();

MyClass.myVariable = 5;  //This change is reflected in both instances

final完全无关,它是定义一次初始化的一种方法。您可以在定义变量时初始化,也可以在构造函数中初始化,无其他地方。

note关于最终方法和最终类的注释,这是一种明确声明不能分别重写/扩展方法或类的方法。

额外阅读 因此,关于静态主题,我们正在谈论它可能具有的其他用途,有时在静态块中使用。使用静态变量时,有时需要在使用类之前设置这些变量,但是不幸的是您没有构造函数。这就是static关键字的所在。

public class MyClass {

    public static List<String> cars = new ArrayList<String>();

    static {
        cars.add("Ferrari");
        cars.add("Scoda");
    }

}

public class TestClass {

    public static void main(String args[]) {
        System.out.println(MyClass.cars.get(0));  //This will print Ferrari
    }
}

您一定不要将其与实例初始化程序块混淆,后者在每个实例的构造函数之前被调用。


根据您提供的输入,您可以消除所有的困惑……final is entirely unrelated, it is a way of defining a once only initialization. You can either initialize when defining the variable or within the constructor, nowhere else.
令人沮丧的thakre 2014年

2
事情应该简单明了。接受的答案是。。。冗长。

22

两者确实并不相似。static字段是不属于类的任何特定实例的字段。

class C {
    public static int n = 42;
}

在这里,该static字段n与的任何特定实例无关,C但通常与整个类相关联(这就是为什么C.n可以使用它来访问它)。您是否仍可以使用的实例C来访问n?是的-但这不是特别好的做法。

final 另一方面,它表明特定变量在初始化后不能更改。

class C {
    public final int n = 42;
}

在这里,n因为是,所以无法重新分配final。另一个区别是,可以声明任何变量final,而并非每个变量都可以声明为静态。

同样,可以声明类以final指示它们不能扩展:

final class C {}

class B extends C {}  // error!

类似地,可以将方法声明为final,以指示扩展类不能覆盖它们:

class C {
    public final void foo() {}
}

class B extends C {
    public void foo() {}  // error!
}

感谢您的投入。代码给出错误:类C {public static int n = 42; 它表示该字段不能以非静态类型声明静态。为什么我不能声明Cn?
TechnoCorner

@TechnoCorner只有顶级类(public定义文件的潜在类)或static内部类才能定义static变量。其他内部类是外部类的实例,并且不能具有静态变量。
zapl 2012年

17

最后 -

1)当我们将“ final ”关键字应用于变量时,该变量的值保持不变。(或)一旦我们将变量声明为final,则该变量的值将无法更改。

2)在程序的生命周期中变量值不发生变化时非常有用

静态的 -

1)当我们将“ static ”关键字应用于变量时,表示它属于类。
2)当我们将“ static ”关键字应用于方法时,这意味着无需创建类的任何实例即可访问该方法



3

静态和最终有一些大的区别:

静态变量或类将始终在(几乎)任何地方都可用。Final只是一个关键字,表示无法更改变量。因此,如果有:

public class Test{    
   public final int first = 10;
   public static int second = 20;

   public Test(){
     second = second + 1
     first = first + 1;
   }
}

该程序将一直运行,直到尝试更改“第一个”整数,这将导致错误。在此类之外,如果您实例化了该类,则只能访问“第一个”变量。这与“第二”始终可用。


3

像演讲者一样思考一个对象。如果Speaker是一个类,它将具有不同的变量,例如音量,高音,低音,颜色等。您可以在定义Speaker类时定义所有这些字段。例如,您使用静态修饰符声明了color字段,这意味着您要告诉编译器该变量确实存在一个副本,而不管实例被实例化了多少次。

宣告

static final String color = "Black"; 

将确保每当实例化此类时,除非未更改,否则color字段的值将为“ Black”。

public class Speaker {

static String color = "Black";

}

public class Sample {

public static void main(String args[]) {
    System.out.println(Speaker.color); //will provide output as "Black"
            Speaker.color = "white";
    System.out.println(Speaker.color);  //will provide output as "White"
}}

注意:现在,一旦您将扬声器的颜色更改为final,则此代码将不会执行,因为final关键字可确保该字段的值永不更改。

public class Speaker {

static final String color = "Black";

}

public class Sample {

public static void main(String args[]) {
    System.out.println(Speaker.color); //should provide output as "Black"
            Speaker.color = "white"; //Error because the value of color is fixed.  
    System.out.println(Speaker.color); //Code won't execute.
}}

您可以将此代码直接复制/粘贴到模拟器中,然后尝试。


2

轻松区别

Final:表示变量的值是Final,并且不会在任何地方更改。如果说final x = 5,则表示x不能更改,它的值对每个人都是final。

静态的:表示它只有一个对象。假设您有x = 5,在内存中有x = 5并且它存在于一个类中。如果您创建类的对象或实例,则意味着存在一个表示该类及其变量和方法的特定框。如果您创建该类的其他对象或实例,则意味着同一类的两个框在内存中具有不同的x。如果在不同位置调用两个x并更改其值,则它们的值将不同。框1具有x,x的x = 5,框2具有x = 6,但是如果将x设为静态,则意味着无法再次创建它。您可以创建类的对象,但是该对象中将没有其他x。如果x是静态的,则框1和框2都将具有相同的x,其值为5。是的,我可以在任何不是最终值的地方更改static的值。因此,如果我说框1具有x且我将其值更改为x = 5,然后我又创建了另一个框,即box2,则将box2 x的值更改为x = 6。然后,由于X是静态的,所以两个框都具有相同的x。并且两个box都将box的值设为6,因为box2会将5的值覆盖为6。

final和static完全不同。Final不能更改为final。静态,将保持不变,但可以更改。

“这是一个例子。记住静态变量总是用它们的类名来调用。因为它们只是该类所有对象的一个​​。所以,类A的x = 5,我可以通过Ax = 6来调用和更改它。 ”


1

静态是类中任何对象都可以调用的东西,它本质上属于对象类型。

变量可以是整个类的最终变量,仅表示不再可以更改。只能设置一次,尝试再次设置将导致引发错误。出于多种原因,它很有用,也许您想声明一个不能更改的常量。

一些示例代码:

class someClass
{
   public static int count=0;
   public final String mName;

   someClass(String name)
   {
     mname=name;
     count=count+1;
   }

  public static void main(String args[])
  {
    someClass obj1=new someClass("obj1");
    System.out.println("count="+count+" name="+obj1.mName);
    someClass obj2=new someClass("obj2");
    System.out.println("count="+count+" name="+obj2.mName);
  }
}

Wikipedia包含Java关键字的完整列表。


您对特定对象是什么意思?你能说明一下吗?
TechnoCorner

0

我不会在这里给出完整的答案。我的建议是着重于理解它们各自的作用,然后应该清楚地看到它们的作用是完全不同的,以及为什么有时将它们一起使用。

static是针对类成员(属性和方法)的,与实例(非静态)成员形成对比。我建议阅读 Java教程中的“了解实例和类成员”。我也可以用在static块中,但是我一开始就不会担心。

final如果将其应用于变量,方法,类或其他情况,则具有不同的含义。在这里,我更喜欢Wikipedia的解释


-1

尽管变量的一个副本遍历整个应用程序,但是可以更改静态变量值,而最终变量值只能初始化一次,并且不能在整个应用程序中更改。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.