static关键字用来声明静态变量或者是静态方法。静态变量和静态方法的重要特征是可以在对象实例化之前调用,静态变量或者静态方法不需要通过对象来进行访问,可以直接通过类名来访问。
当static用来声明变量时,此变量称之为静态变量。对于一个类来说,被static修饰的变量只有一份内存空间,而非static类型的变量对于每个对象都有一个存储空间。用static声明的类属性可以说是公共属性,这个类的所有对象共享这个公共属性,所有对象共享一份内存空间,因此,用static声明的变量也称之为“类变量”。
当static用来修饰方法时,此方法称之为静态方法,也称之为类方法。静态方法的用途之一是在不创建任何对象的前提下就可以调用它(对象实例化之前),这一点对于main方法来说至关重要(作为程序运行的入口)。
需要注意的是:
1、静态变量可以在静态方法中使用,也可以在非静态方法中使用。但是静态方法只能使用静态类型的变量,而不能使用非静态类型的变量(或者说是成员)。
2、和CPP中不同,static不会改变变量或者方法的作用域。
3、对于static和this的关系,this返回的是当前对象的引用,可以在静态方法中调用this,表示通过对象进行访问。但是静态方法不需要这样做,它不需要实例化调用,可以直接通过类名调用。
4、最后一点,由于static是伴随着类而出现的,一定是在类调用之前就已经完成了内存空间的开辟,一定是全局变量,所以static关键字一定不可以用于局部变量的修饰。
最后再来说一下静态代码块儿,就是将某一部分代码块儿用static声明,称之为静态代码块。静态代码块儿可以不包含在任何的方法体中。当类被载入时,静态代码块儿被执行,并且只执行一次,静态代码块常常用来进行类属性的初始化。举个例子来说,定义一个Person的类,在通过一个Test载入Person。
public class Person {
public Person() {
System.out.println("Step First.");//第3_2步打印,以及第四步打印
}
static{
System.out.println("Step Second.");//第3_1步打印,且只执行一次
}
}
public class Test {
static{
System.out.println("Step Third.");//第一步打印
}
public static void main(String[] args) {
System.out.println("Step Fourth.");//第二步打印
new Person();
new Person();
}
}
最后测试的结果是和代码中注释的顺序是相同的。
很多书中都把static标记为静态,但并不能准确的说出static的真正用途,static的真正作用在于区分成员变量、方法、内部类、初始化块儿到底是属于实例还是属于类本身。有static修饰的成员属于类本身,而不属于实例对象,没有static修饰的成员则属于类的对象。
由于static的原因,就出现了一个梗:静态成员不能访问非静态成员。因为static修饰的方法的主调总是类本身,如果在static修饰的方法中出现this引用,就会导致this无法引用有效的对象,注意,这里static修饰的属于类本身,而this返回的是类的对象。
static修饰的成员完全不属于类的实例对象,不能使用实例去调用static修饰的对象和方法,而应该直接使用类去调用static修饰的对象和方法。
但是对于static修饰的类变量在什么时候使用?仍是一个问题,因为类变量,成员变量和局部变量的作用域不同,作用时间也不同,不恰当的使用一方面会扩大变量的生存时间,增大内存开销.另一方面会扩大变量的作用域,不利于提高程序的内聚性.一般在下面几种情况发生时使用static修饰为类变量:
1、定义的变量用于描述某个类或者某个对象固有的信息
2、变量用来保存类或者运行时的状态信息
3、变量信息需要在类的多个方法之间共享