189

我总是对javastatic中的andfinal关键字感到困惑。

它们有何不同?

4

11 回答 11

258

static关键字可用于4种场景

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

我们先来看看静态变量和静态方法。

静态变量

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

静态方法

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

静态类

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

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

Java 中没有顶级静态类。

边注:

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

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

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

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

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

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

当在方法体中定义匿名内部类时,在该final方法范围内声明的所有变量都可以从内部类中访问。一旦它被赋值,最终变量的值就不能改变。

于 2012-12-07T23:59:02.690 回答
41

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
    }
}

您不能将此与在每个实例的构造函数之前调用的实例初始化程序块混淆。

于 2012-12-07T23:52:22.273 回答
26

两者真的不一样。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!
}
于 2012-12-07T23:54:27.643 回答
23

static表示该类的所有实例共享的内存中只有一个变量副本。

final关键字只是意味着无法更改值。如果没有final,任何对象都可以更改变量的值。

于 2016-10-16T21:26:08.100 回答
22

最终的 -

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

2)当变量值在程序的生命周期内不改变时很有用

静止的 -

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

于 2014-04-07T23:17:26.230 回答
6

想象一个像扬声器这样的物体。如果 Speaker 是一个类,它将具有不同的变量,例如音量、高音、低音、颜色等。您在定义 Speaker 类时定义所有这些字段。例如,您使用 static 修饰符声明颜色字段,这意味着您告诉编译器该变量仅存在一个副本,无论该类已被实例化多少次。

声明

static final String 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.
}}

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

于 2014-01-28T22:14:52.183 回答
4

容易区分,

Final:表示变量的值是 Final 并且不会在任何地方改变。如果你说 final x = 5 这意味着 x 不能改变,它的值对每个人都是最终的。

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

Both final and static are totally different. Final which is final can not be changed. static which will remain as one but can be changed.

"This is an example. remember static variable are always called by their class name. because they are only one for all of the objects of that class. so Class A has x =5, i can call and change it by A.x=6; "

于 2019-04-01T18:34:23.193 回答
3

static 和 final 有一些很大的区别:

静态变量或类总是可以从(几乎)任何地方获得。final 只是一个关键字,表示不能更改变量。所以如果有:

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

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

该程序将一直运行,直到它尝试更改“第一个”整数,这将导致错误。在这个类之外,如果你已经实例化了这个类,你将只能访问“first”变量。这与始终可用的“秒”相反。

于 2012-12-07T23:56:41.500 回答
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 关键字的完整列表。

于 2012-12-07T23:50:16.157 回答
0

我不会尝试在这里给出完整的答案。我的建议是专注于了解它们每个人的作用,然后应该清楚地看到它们的效果是完全不同的,以及为什么有时它们会一起使用。

static用于类的成员(属性和方法),并且必须与实例(非静态)成员对比来理解。我建议阅读Java 教程中的“了解实例和类成员”。我也可以在static块中使用,但一开始我不会担心它。

final如果应用于变量、方法、类或其他一些情况,则具有不同的含义。在这里,我更喜欢维基百科的解释

于 2012-12-08T00:03:24.093 回答
-1

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

于 2018-11-21T16:26:22.013 回答