静态和最终的区别?

时间:2012-12-07 23:48:34

标签: java

我总是对 java 中的staticfinal个关键字感到困惑。

他们有什么不同?

11 个答案:

答案 0 :(得分:215)

static关键字可用于4种情况

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

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

静态变量

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

静态方法

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

静态类

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

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

Java中没有顶级静态类。

旁注:

  

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

在几个不同的上下文中使用

final关键字来定义以后无法更改的实体。

  • 无法对final类进行子类化。这样做是出于安全和效率的原因。因此,许多Java标准库类都是final,例如java.lang.Systemjava.lang.Stringfinal类中的所有方法都隐含final

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

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

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

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

答案 1 :(得分:35)

静态表示它属于类而非实例,这意味着在特定的所有实例之间只共享该变量/方法的一个副本。

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 关于最终方法和最终类的说明,这是一种明确声明无法分别覆盖/扩展方法或类的方法。

额外阅读 所以关于静态的话题,我们讨论的是它可能具有的其他用途,它有时用在静态块中。使用静态变量时,有时需要在使用类之前设置这些变量,但遗憾的是,您没有获得构造函数。这是静态关键字的用武之地。

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

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

答案 2 :(得分:21)

两者真的不相似。 static字段是不属于任何特定类的字段。

class C {
    public static int n = 42;
}

此处,static字段nC的任何特定实例无关,但与整个类无关(这就是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!
}

答案 3 :(得分:14)

最终 -

1)当我们申请&#34; 最终&#34; 变量的关键字,该变量的值保持不变。             (要么)   一旦我们将变量声明为 final ,就无法更改该变量的值。

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

静态

1)当我们申请&#34; 静态&#34; 变量的关键字,表示它属于类    2)当我们申请&#34; 静态&#34;关键字方法,表示无需创建任何类的实例即可访问方法

答案 4 :(得分:6)

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

final关键字仅表示该值无法更改。没有final,任何对象都可以更改变量的值。

答案 5 :(得分:3)

静态和最终有一些很大的不同:

静态变量或类总是可以从(几乎)任何地方获得。 Final只是一个关键字,意味着变量无法更改。所以,如果有:

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

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

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

答案 6 :(得分:3)

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

声明

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

注意:现在,一旦您更改了扬声器的颜色,最终此代码就不会执行,因为最终关键字会确保该字段的值永远不会更改。 < / p>

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

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

答案 7 :(得分: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);
  }
}

维基百科包含java keywords的完整列表。

答案 8 :(得分:1)

轻松区别

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

静态:表示它只有一个对象。假设您有x = 5,在内存中有x = 5并且它存在于一个类中。如果您创建类的对象或实例,则意味着存在一个表示该类及其变量和方法的特定框。如果您创建该类的另一个对象或实例,则意味着同一类的两个框在内存中具有不同的x。如果在不同位置调用两个x并更改其值,则它们的值将不同。框1的x的x = 5,框2的x =6。但是,如果将x设为静态,则意味着无法再次创建它。 您可以创建类的对象,但该对象中将没有不同的x。 如果x是静态的,则框1和框2都将具有相同的x,其值为5。是的,我可以在任何非static的地方更改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,我可以通过A.x = 6来调用和更改它; “

答案 9 :(得分:0)

我不会试着在这里给出完整的答案。我的建议是专注于理解他们每个人所做的事情,然后应该清楚地看到他们的影响是完全不同的,为什么有时他们会一起使用。

static用于类的成员(属性和方法),并且必须与实例(非静态)成员进行比较。我建议在The Java Tutorials中阅读"Understanding Instance and Class Members"。我也可以在static块中使用,但我不会担心它的开始。

final具有不同的含义,如果它适用于变量,方法,类或其他一些情况。在这里,我更喜欢Wikipedia explanations

答案 10 :(得分:-1)

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