Java static关键字的用法(非常详细)
作为 Java 程序员,从我们接触第一个 Java 程序开始就一直看到 static 这个关键字,编写主方法来运行某个 Java 类时,这个主方法就被声明为 static,这个关键字出现得十分频繁。
实际上 static 不仅可以修饰方法,也可以用来修饰变量和语句块,下面我们将学习 static 的这些用法。
实例方法是对象级的方法,所以如果要想访问它们,就必须先创建一个对象,然后通过对象进行访问。
比如下面实例中类内部定义的 instanceMethod() 方法,由于它是实例方法,因此必须先通过 new 创建一个 StaticTest 对象后才能通过所创建的对象去调用该方法。
继续在 StaticTest 类中定义 staticMethod() 方法,该方法属于静态方法,可以通过 StaticTest 类直接进行调用,例如:
相应地,静态变量是指类中声明为 static 的变量,它是类级的变量,所以也称为类变量。
下面的程序展示了实例变量与静态变量的区别:
对于所有对象来说静态变量只有一个,而实例变量却是每个对象都拥有一个。

图 1 静态变量与实例变量
如上图所示,变量 a 只有一个,所有对象共享一个变量 a,但变量 b 却有多个。
当一个变量被所有对象共享时可以定义为静态变量,而当一个变量在每个对象中都需要有各自的值时,则要定义为实例变量。比如在 Math 类中定义圆周率 π,可以定义为“public static double PI = 3.14159265;”,所有 Math 对象都可以共享这个值。
静态块只在类加载时被执行一次,而并非每次创建对象时都会执行。
实际上 static 不仅可以修饰方法,也可以用来修饰变量和语句块,下面我们将学习 static 的这些用法。
Java 实例方法与静态方法
所谓实例方法,就是指在类中定义的非 static 方法。实例方法是对象级的方法,所以如果要想访问它们,就必须先创建一个对象,然后通过对象进行访问。
比如下面实例中类内部定义的 instanceMethod() 方法,由于它是实例方法,因此必须先通过 new 创建一个 StaticTest 对象后才能通过所创建的对象去调用该方法。
public class StaticTest { public void instanceMethod() { System.out.println("实例方法"); } }再看静态方法,在类中使用 static 来修饰的方法就是静态方法,它属于类级的方法,所以可以直接通过类来访问它。
继续在 StaticTest 类中定义 staticMethod() 方法,该方法属于静态方法,可以通过 StaticTest 类直接进行调用,例如:
public class StaticTest { public void instanceMethod() { System.out.println("实例方法"); } public static void staticMethod() { System.out.println("静态方法"); } public static void main(String[] args) { StaticTest st = new StaticTest(); st.instanceMethod(); StaticTest.staticMethod(); } }主方法中分别展示了如何调用实例方法和静态方法。如果某个方法可以供所有实例共享,就可以声明为静态方法,比如工具类中会经常使用静态方法,或者不想使某些方法被重写时也可以声明为静态方法。
Java实例变量与静态变量
实例变量是指类中的非 static 变量,它是对象级的变量。由类创建出的每个对象都有属于自己的变量,实例变量只能通过对应的对象去访问。相应地,静态变量是指类中声明为 static 的变量,它是类级的变量,所以也称为类变量。
下面的程序展示了实例变量与静态变量的区别:
public class StaticTest2 { public static int a = 10; public int b; public static void main(String[] args) { System.out.println(StaticTest2.a); StaticTest2 s1 = new StaticTest2(); StaticTest2 s2 = new StaticTest2(); StaticTest2 s3 = new StaticTest2(); s1.b = 0; s2.b = 10; s3.b = 20; System.out.println(s1.b); System.out.println(s2.b); System.out.println(s3.b); } }变量 a 为静态变量,而变量 b 为实例变量,我们可以直接通过 StaticTest2 类来访问静态变量 a,而 s1、s2 和 s3 三个对象都各自拥有自己的实例变量 b。
对于所有对象来说静态变量只有一个,而实例变量却是每个对象都拥有一个。

图 1 静态变量与实例变量
如上图所示,变量 a 只有一个,所有对象共享一个变量 a,但变量 b 却有多个。
当一个变量被所有对象共享时可以定义为静态变量,而当一个变量在每个对象中都需要有各自的值时,则要定义为实例变量。比如在 Math 类中定义圆周率 π,可以定义为“public static double PI = 3.14159265;”,所有 Math 对象都可以共享这个值。
Java静态块
静态块是指以static{ }
的形式包围起来的语句块,它的主要作用是在类加载时进行一些初始化工作,比如初始化类的静态变量,静态块会在类加载时被执行。静态块只在类加载时被执行一次,而并非每次创建对象时都会执行。
public class StaticTest3 { public static int a = 10; static { System.out.println("a=" + a); a = 20; } public static void main(String[] args) { System.out.println("a=" + a); } }程序中,静态块对静态变量 a 进行赋值,运行时会先在静态块中输出“a=10”,然后才在主方法中输出“a=20”。