静态和最终的区别?
我一直在Java中的 static
和final
关键字之间混淆。
他们有什么不同?
static关键字可以用于4个场景
- 静态variables
- 静态方法
- 静态的代码块
- 静态嵌套类
我们先来看静态variables和静态方法。
静态variables
- 它是属于类而不是对象(实例)的variables。
- 在执行开始时,静态variables只被初始化一次。 在初始化任何实例variables之前,这些variables将被初始化。
- 一个副本由该类的所有实例共享。
- 静态variables可以直接通过类名访问,不需要任何对象。
- 语法:
Class.variable
静态方法
- 它是属于类而不是对象(实例)的方法。
- 静态方法只能访问静态数据。 它不能访问非静态数据(实例variables),除非它已经/创build了一个类的实例。
- 一个静态方法只能调用其他静态方法,不能调用非静态方法,除非它有/创build一个类的实例。
- 静态方法可以通过类名直接访问,不需要任何对象。
- 语法:
Class.methodName()
- 静态方法无论如何不能引用
this
或super
关键字。
静态类
Java也有“静态嵌套类”。 一个静态嵌套类只是一个不隐式地引用外部类的实例。
静态嵌套类可以有实例方法和静态方法。
Java中没有这样的顶级静态类。
边注:
main方法是
static
因为它必须是可以访问的,以便在任何实例化之前运行应用程序。
在几个不同的上下文中使用final
关键字来定义一个以后不能改变的实体。
-
final
堂课不能分类。 这是出于安全和效率的原因。 因此,许多Java标准库类都是final
,例如java.lang.System
和java.lang.String
。final
课中的所有方法都是隐含的final
。 -
final
方法不能被子类覆盖。 这用于防止子类中的意外行为改变可能对类的function或一致性至关重要的方法。 -
final
variables只能通过初始化或赋值语句初始化一次。 它不需要在声明点初始化:这被称为blank final
variables。 一个类的一个空白的final实例variables必须在声明它的类的每个构造函数的末尾明确赋值; 类似地,一个空白的最终静态variables必须明确地分配给它声明的类的静态初始化程序; 否则,在这两种情况下都会发生编译时错误。
注意:如果variables是一个引用,这意味着该variables不能被重新绑定来引用另一个对象。 但是它引用的对象仍然是可变的,如果它最初是可变的。
当一个匿名内部类被定义在一个方法体内时,所有在该方法范围内声明为final
variables都可以从内部类中访问。 一旦分配完毕,最终variables的值就不能改变。
静态意味着它属于类而不是实例,这意味着在特定类的所有实例之间共享该variables/方法只有一个副本。
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是完全不相关的,它是定义一次只初始化的一种方式。 您可以在定义variables时或在构造函数中进行初始化,在其他地方无法进行初始化。
注意关于最终方法和最终类的说明,这是明确指出方法或类不能被重写/扩展的一种方法。
额外阅读所以关于静态的话题,我们正在谈论它可能有的其他用途,它有时用在静态块中。 当使用静态variables时,有时需要在使用类之前设置这些variables,但不幸的是,您不会得到构造函数。 这是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 } }
你不能把它与在每个实例的构造函数之前调用的实例初始化块混淆。
这两个真的不相似。 static
字段是不属于某个类的任何特定实例的字段。
class C { public static int n = 42; }
在这里, static
字段n
不与C
任何特定实例相关联,而是与整个类相关联(这就是为什么可以使用Cn
来访问它)。 你还能用C
一个实例来访问n
吗? 是的 – 但这不被认为是特别好的做法。
final
另一方面表明特定variables在初始化后不能改变。
class C { public final int n = 42; }
在这里, n
不能被重新分配,因为它是final
。 另一个区别是任何variables都可以声明为final
,而不是每个variables都可以声明为static。
另外,类可以声明为final
,表示它们不能被扩展:
final class C {} class B extends C {} // error!
同样,方法可以被声明为final,以表明它们不能被扩展类重写 :
class C { public final void foo() {} } class B extends C { public void foo() {} // error! }
最后 –
1)当我们将“ final ”关键字应用于variables时 ,该variables的值保持不变。 (或)一旦我们声明一个variables为final ,那个variables的值就不能改变。
2)在程序生存期间, variables值不变的情况下有用
静态的 –
1)当我们将“ 静态 ”关键字应用于variables时 ,这意味着它属于类。
2)当我们将“ 静态 ”关键字应用到一个方法时 ,这意味着该方法可以被访问而不需要创build任何类的实例
静态和最终有一些很大的区别:
静态variables或类将始终可用(几乎)任何地方。 最终只是一个关键字,意味着一个variables不能改变。 所以如果有:
public class Test{ public final int first = 10; public static int second = 20; public Test(){ second = second + 1 first = first + 1; } }
该程序将运行,直到它试图改变“第一个”整数,这将导致一个错误。 在这个类之外,如果你已经实例化了这个类,那么你只能访问“第一个”variables。 这与“秒”形成鲜明对比,而“秒”则始终可用。
想想像一个扬声器的对象。 如果扬声器是一个类,它将有不同的variables,如音量,高音,低音,颜色等。您定义扬声器类时定义所有这些字段。 例如,您使用静态修饰符声明了颜色字段,这意味着您要告诉编译器该variables存在一个副本,而不pipe该类实例化了多less次。
声明
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关键字可确保该字段的值永远不会更改。
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. }}
你可以直接复制/粘贴这个代码到你的模拟器中,然后尝试。
静态是类中的任何对象都可以调用的东西,它本质上属于对象types。
一个variables对于一个特定的对象来说可能是最终的,这就意味着它不会再改变。 它只能被设置一次,试图重新设置会导致错误被抛出。 这是有用的,有很多原因,也许你想给一个对象的名字,这是不能改变的。
一些示例代码:
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关键字的完整列表。
静态意味着在类的所有实例共享的内存中只有一个variables副本。 最后的关键字只是意味着值不能改变。 没有final ,任何对象都可以改变variables的值。
我不会在这里给出完整的答案。 我的build议是把重点放在理解他们每个人做什么,然后应该清楚地看到他们的影响是完全不同的,为什么有时他们一起使用。
static
是一个类的成员(属性和方法),它必须与实例(非静态)成员相对照。 我build议阅读“ Java教程”中的“理解实例和类成员” 。 我也可以使用static
块,但我不会担心它的一个开始。
final
根据variables,方法,类或其他情况应用于不同的含义。 在这里我更喜欢维基百科的解释 。
- MSIL和Java字节码的区别?
- 是否需要在onActivityResult()中使用super.onActivityResult()?
- 在jUnit中有多个RunWith语句
- 如何更改一个java.util.Calendar / Date的TIMEZONE
- Java String.valueOf(null)抛出NPE,但Object a = null; String.valueOf(a)返回'null'
- 如何在窗口closures时closuresJavaFX应用程序?
- setProperty必须被SOAPMessage的所有子类覆盖
- 为什么我无法在Maven中使用Junittesting来访问src / test / resources?
- 我如何计算两个ArrayLists之间的差异?