一篇讲的很好的博客
https://www.cnblogs.com/dolphin0520/p/3799052.html
static关键字的特殊之处在于 被static修饰的变量和方法,可以直接通过类来访问,而无需创建对象。
eg.
public class Animal
{
public static String name=="Animal";
Animal(String name)
{
this.name=name;
}
public static void run()
{
System.out.println("run");
}
public static void main(String[] args)
{
Animal.run(); //直接通过类名来访问static方法
System.out.println(Animal.name); //直接通过类名来访问static变量
}
}
可以看到,上例直接通过类名Animal访问了static方法和static变量,而没有实例化对象。
static关键字主要有三种用法:静态变量、静态方法、静态代码块。
1.静态变量
static变量即静态变量,在编译时由系统分配内存,直到程序停止运行才会释放。静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
注意:静态变量位于类中,方法外,不能位于方法内部!
2.静态方法
static方法不依赖于任何对象就可以进行访问,由于没有创建对象,所以static方法没有this。并且静态方法内不能调用非静态方法,不能访问非静态变量(因为非静态变量和方法的存在依赖于对象)。而在非静态成员方法中是可以访问静态成员方法/变量的。
注意:父类的static方法不能被子类重写。
3.静态代码块
被static关键字修饰的代码块,在类初次被加载的时候执行,且仅执行这一次。静态代码块可以用来优化程序性能。
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
Test t1=new Test();
Test t2=new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
执行结果为:
base static
test static
base constructor
test constructor
base constructor
test constructor
在执行开始,先要寻找到main方法,因为main方法是程序的入口。但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。实例化第一个Test对象时,首先调用父类的构造器,再调用自己的构造器;第二个同理。
可以看到,static代码块只在类初次加载时执行一次。