https://github.com/LingCoder/OnJava8/blob/master/docs/book/03-Objects-Everywhere.md
类是对象的外观及行为方式的描述。通常只有在使用 new 创建那个类的对象后,数据存储空间才被分配,对象的方法才能供外界调用。这种方式在两种情况下是不足的。
-
有时你只想为特定字段(注:也称为属性、域)分配一个共享存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建对象。
-
创建一个与此类的任何对象无关的方法。也就是说,即使没有创建对象,也能调用该方法。
static 关键字(从 C++ 采用)就符合上述两点要求。当我们说某个事物是静态时,就意味着该字段或方法不依赖于任何特定的对象实例 。 即使我们从未创建过该类的对象,也可以调用其静态方法或访问其静态字段。相反,对于普通的非静态字段和方法,我们必须要先创建一个对象并使用该对象来访问字段或方法,因为非静态字段和方法必须与特定对象关联 。
一些面向对象的语言使用类数据(class data)和类方法(class method),表示静态数据和方法只是作为类,而不是类的某个特定对象而存在的。有时 Java 文献也使用这些术语。
我们可以在类的字段或方法前添加 static 关键字来表示这是一个静态字段或静态方法。 代码示例:
class StaticTest {
static int i = 47;
}
现在,即使你创建了两个 StaticTest 对象,但是静态变量 i 仍只占一份存储空间。两个对象都会共享相同的变量 i。 代码示例:
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
st1.i 和 st2.i 指向同一块存储空间,因此它们的值都是 47。引用静态变量有两种方法。在前面的示例中,我们通过一个对象来定位它,例如 st2.i。我们也可以通过类名直接引用它,这种方式对于非静态成员则不可行:
StaticTest.i++;
++ 运算符将会使变量结果 + 1。此时 st1.i 和 st2.i 的值都变成了 48。
使用类名直接引用静态变量是首选方法,因为它强调了变量的静态属性。类似的逻辑也适用于静态方法。我们可以通过对象引用静态方法,就像使用任何方法一样,也可以通过特殊的语法方式 Classname.method() 来直接调用静态字段或方法 。 代码示例:
class Incrementable {
static void increment() {
StaticTest.i++;
}
}
上例中,Incrementable 的 increment() 方法通过 ++ 运算符将静态数据 i 加 1。我们依然可以先实例化对象再调用该方法。 代码示例:
Incrementable sf = new Incrementable();
sf.increment();
当然了,首选的方法是直接通过类来调用它。代码示例:
Incrementable.increment();
相比非静态的对象,static 属性改变了数据创建的方式。同样,当 static 关键字修饰方法时,它允许我们无需创建对象就可以直接通过类的引用来调用该方法。正如我们所知,static 关键字的这些特性对于应用程序入口点的 main() 方法尤为重要。