Concept
通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则实际上并未获得任何对象。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。
有两种情形用上述方法是无法解决的。一种是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。另一种情形是,希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用这个方法。
通过static关键字可以满足这两方面的需要。当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象关联在一起。所以,即使从未创建某个类的任何对象,也可以调用非static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法。因为非static域和方法必须知道它们一起运作的特定对象。
有些面向语言语言采用类数据和类方法两个术语,代表那些数据和方法只是作为整个类,而不是类的某个特定对象而存在的。
static字段
class test{
static int i = 47;
}
即使创建了两个test对象,test.i也只有一份存储空间,这两个对象共享同一个i。如下,st1.i = st2.i
test st1 = new test();
test st2 = new test();
引用static变量有两种方法。一种方法是如上面所说,可以通过一个对象去定位它,如st1.i;也可以通过其类名直接引用,而这对于非静态成员则不行。
test.i++;
此时,st1.i和st2.i仍具有相同的值48。
static 方法
- 被static修饰的方法也叫做静态方法,因为对于静态方法来说是不属于任何实例对象的,那么就是说在静态方法内部是不能使用this的,因为既然不属于任何对象,那么就更谈不上this了。
- 我们既可以像其他方法一样,通过一个对象来引用某个静态方法,也可以通过特殊的语法形式ClassName.method()加以引用。
定义静态方法
static void increase(){ test.i++; }
两种调用方式
test st3 = new test();
st3.increase();
test.increase();
尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份储存空间,而非static字段则是对每个对象有一个储存空间),但如果static作用于方法,差别却没有那么大。static方法的一个重要用法是在不创建任何对象的前提下就可以调用它。
static 静态块
- Java中的静态块主要有两个作用:用于初始化静态数据成员;它在类加载时在main方法之前执行
- static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
class test{
static{
System.out.println("我是静态块");
}
public static void main(String[] args){
System.out.println("我是主程序");
}
}
运行结果
我是静态块
我是主程序
Conclusion
- 在类被加载的时候,就会去加载被static修饰的部分。
- static是不允许用来修饰局部变量。
- this和super两个关键字不能在静态上下文中使用。因为静态是随着类的加载而加载,而this是随着对象的创建而存在的。静态比对象优先存在。
- 静态只能访问静态。非静态既可以访问非静态的,也可以访问静态的。
静态方法不能直接使用非静态数据成员或调用非静态方法。 - 生命周期的区别:(1)静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。(2)非静态的成员数据是随着对象的创建而存在,随着对象被垃圾回收器回收而消失。
Question
- 为什么java main方法是静态的?
这是因为调用静态方法不需要对象,如果它是非静态方法,JVM首先要创建对象,然后调用main()方法,这将导致额外的内存分配的问题。