Java:Static关键字

Static介绍与用法

  通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则,实际上并未获得任何对象。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。
  有两种情形用上述方法是无解的。一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。另一种情形是,希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能调用这个方法。
  通过static关键字可以满足这两方面的需要。当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起。所以,即使从未创建某个类的对任何对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法。因为非static域和方法必须知道他们一起运作的特定对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class StaticTest {
static int i = 47;
int j = 47;
static void incrementi(){
i++;
}
void incrementj(){
j++;
}
}


public class test {
public static void main(String[] args) {

StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();

System.out.println("st1.i: " + st1.i);
System.out.println("st2.i: " + st2.i);

st1.incrementi();
System.out.println("st1.incrementi()后的st1.i: " + st1.i);
System.out.println("st1.incrementi()后的st2.i: " + st2.i);

st1.incrementj();
System.out.println("st1.incrementj()后的st1.j: " + st1.j);
System.out.println("st1.incrementj()后的st2.j: " + st2.j);
}
}

//Output:
st1.i: 47
st2.i: 47
st1.incrementi()后的st1.i: 48
st1.incrementi()后的st2.i: 48
st1.incrementj()后的st1.j: 48
st1.incrementj()后的st2.j: 47

以上代码中i是静态变量,incrementi()是静态方法。创建两个对象并且只对其中一个执行incrementi()方法得出的输出中,两个对象的i属性都加了1。incrementj()不是静态方法,所以st1执行incrementj()后,st2的j值不变。

  将字段或方法设定为static,即使创建了两个StaticTest对象,StaticTest.i也只有一份存储空间,这两个对象公像一个i,上例中的st1.i和st2.j指向同一存储空间。

引用static对象时可以通过类名直接引用:

1
StaticTest.i++

或者因为incrementi()是一个静态方法,也可以直接通过类调用:

1
StaticTest.incrementi()

  尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象有一个存储空间),但是如果static作用于某个方法,差别却没有那么大。static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它,这一点对定义main()方法很重要,这个方法是运行一个应用时的一个入口点。

个人理解

  对于Static的理解我个人认为重点是认识到Static的字段,不管创建多少个对象,字段都是指向同一个存储空间,也就是说都是同时改变的。

参考资料

《JAVA编程思想第四版》


Q:为什么main函数中不能定义static变量?
A:只有类才存在静态的变量,方法只能对静态变量的操作,不能在方法内试图定义静态变量。