我们可以基于一个类创建多个对象,每个对象都拥有自己的成员,所有成员变量的值是根据对象而存在的,有些时候我们希望一个类的所有对象共享一个成员,这就用到了static静态关键字
被静态关键字修饰的成员属于静态成员,它属于整个类所有,而并不仅仅是一个对象中的成员所共享,当系统第一次使用该类时,就会为其分配内存空间,直到该类被销毁是才进行资源回收,静态成员也有自己特有的访问方法
static可以修饰变量、方法、代码块
1、静态变量
因为局部静态变量和局部变量的使用方法一样,直接使用即可,所以对于类中定义的静态成员变量,非静态方法可以直接通过变量名访问,不用考虑其他,对于静态方法,最典型的就是public static void main(String[] args)这个入口方法,如果在这样的静态方法内部访问,需要用"类名.静态变量名"的方式进行访问,比如Hello.abc当然也可以先实例化对象,然后通过对象.静态变量名的方式来访问,但是还是推荐使用类名.静态变量名进行访问
2、静态方法
上面说了静态方法内部访问静态成员变量的方法,并且静态方法可以直接访问本类的静态变量和静态方法,不用加任何修饰,访问其他类则推荐使用类名.成员名的方式访问;那么访问普通成员变量呢?不能直接访问,应该先实例化对象,然后通过对象.成员变量名的方式进行访问,但是普通方法可以直接访问静态方法和静态变量;同理静态方法不能直接访问普通方法,也需要实例化对象.方法,这样的方式来访问普通方法。
3、静态代码块
Java在初始化变量的时候可以使用public String name = "abc";这样的方法来初始化变量的值,也可以通过下面代码块实现:
1 public class Hello { 2 public String name; //定义成员变量 3 { //初始化块赋值 4 name = "abc"; 5 } 6 }
可以使用多个初始化块,当创建类的实例时,会依次执行这些代码块,通过static关键字修饰的代码块称为静态代码块;
静态代码块的初始化内容只能执行一次,再次被实例化时将不会被执行;
静态代码块中只能初始化静态变量,不能放置普通变量;
我们可以看个例子:
1 public class Hello { 2 int num1; 3 int num2; 4 static int num3; 5 public Hello(){ 6 num1 = 30; 7 System.out.println("通过构造方法给num1赋值"); 8 } 9 { 10 num2 = 60; 11 System.out.println("通过初始化块给num2赋值"); 12 } 13 static { 14 num3 = 90; 15 System.out.println("通过静态初始化块给num3赋值"); 16 } 17 18 public static void main(String[] args){ 19 Hello he = new Hello(); 20 System.out.println("num1:" + he.num1); 21 System.out.println("num2:" + he.num2); 22 System.out.println("num3:" + num3); 23 Hello he1 = new Hello(); 24 } 25 }
这个输出什么呢?可能输出和我们想象的有点相反,正确输出如下:
通过静态初始化块给num3赋值
通过初始化块给num2赋值
通过构造方法给num1赋值
num1:30
num2:60
num3:90
通过初始化块给num2赋值
通过构造方法给num1赋值
根据上面的输出结果可以看出,在实例化对象时静态初始化块最先执行,然后执行普通初始化块,最后才执行构造方法;并且由于静态初始化块只在类被加载时执行一次,所以第二次实例化对象时没有被执行,这就是静态初始化块的执行顺序和特点
最后总结一点静态和普通就好像是两个权限,普通的好像权限高一些,可以直接操作静态,但是静态要操作普通的则要复杂一些,需要实例化才可以