static修饰符可以用来修饰变量、方法、代码块、内部类。static方法就是没有this的方法,在static方法内部不能调用非静态方法和非静态属性,反过来是可以的。static关键字主要作用就是:
方便在没有创建对象的情况下来调用(方法/变量)。
注意点:
- static修饰的方法中,不能出现非static方法和变量
- static修饰的方法中,不能出现this。原因是this指调用当前方法的对象,而static方法不属于任何对象。
- static修饰的属性和方法与类的加载时间一致
- static不能作用于局部变量。static成员变量属于类,而不属于对象。在方法中定义的局部变量有一定作用范围和生命周期,定义在方法内部就默认了它只能在方法内部使用而不能拓展到别的地方。那么假如在普通方法中定义了静态变量,那么其它方法就不能访问到该变量,既然访问不到就和普通变量一样。
下面看一段代码:
1 public class Demo2 { 2 static { 3 System.out.println("this is demo2"); 4 } 5 { 6 System.out.println("demo2"); 7 } 8 public Demo2() { 9 System.out.println("demo2 constructor"); 10 } 11 } 12 13 public class Demo1 extends Demo2{ 14 static { 15 System.out.println("this is demo1"); 16 } 17 { 18 System.out.println("demo1"); 19 } 20 public Demo1() { 21 System.out.println("demo1 constructor"); 22 } 23 public static void main(String[] args) { 24 new Demo1(); 25 } 26 }
输出结果:this is demo2 this is demo1 demo2 demo2 constructor demo1 demo1 constructor
至于为什么是这个结果,我们来分析一下:执行开始,首先找到main方法,main方法是程序的入口。在执行main方法前,需要加载Demo1类,而在加载Demo1类的时候发现,Demo1类继承自Demo2类,因此先去加载Demo2类。加载Demo2类的时候,发现Demo2类中有static代码块,便首先执行static代码块。Demo2类加载完之后,转而加载Demo1类,发现Demo1类也有static块,执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Demo1()的时候首先会去寻找Demo1的父类Demo2,找到后加载Demo2的代码块,之后调用Demo2的构造器,然后再加载自身的代码块并调用自身的构造器。
再看这段代码:
public class Person { static { System.out.println("Person static"); } public Person(String name) { System.out.println("Person:" + name); } } public class MyClass extends Test { Person person = new Person("myclass"); static { System.out.println("myclass static"); } public MyClass() { System.out.println("myclass constructor"); } } public class Test { Person person = new Person("test"); static { System.out.println("Test static"); } public Test() { System.out.println("test constructor"); } public static void main(String[] args) { new MyClass(); } }
输出结果:Test static myclass static Person static Person:test test constructor Person:myclass myclass constructor
分析一下:
首先找到main方法,在执行main方法前需要加载Test类,因此执行static块。接着执行main方法中new MyClass(),而MyClass类还没被加载,因此需要加载MyClass类。
在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类中的static块。加载完之后,通过构造器生成对象。
在生成对象时,首先初始化父类的成员变量,因此会执行Person person = new Person(),而person类还没被加载过,因此加载Person类。接着就执行Person类中的static块,然后执行父类的构造器。
完成了父类的初始化,然后加来初始化自身了,因此会初始化MyClass中的成员变量Person,最后执行MyClass的构造器。