static
关键词static可以用来修饰方法、变量、代码块,被static定义的变量或者方法,可以直接通过类名来进行引用。
static代码块
static代码块也就是即静态块。可以置于类中的任何地方(除了方法内部),类可以有多个static块。在JVM装载类的时候,静态数据只在类装载(生成.class文件)的时候执行一次,静态代码块也是如此,类中所有的静态块会随着类的加载而被执行,只要类被加载了就会执行,而且只进行一次初始化,主要用于给类进行初始化。
这里有个值得参考的例子
public class Person {
public Person(int id) {
System.out.println("person(" + id + ")");
}
public static void main(String[] args) {
Build b = new Build();
System.out.println("------分割线------");
Build b2=new Build();
}
}
class Build {
/*静态块*/
static{
System.out.println("this is static block!");
}
/*非静态块*/
{
System.out.println("this is non-static block!");
}
Person p1 = new Person(1);//------------1-----------
public Build() {
System.out.println("this is build's block!");
Person p2 = new Person(2);
}
Person p3 = new Person(3);
}
输出结果:
This is static block!
This is non-static block!
person(1)
This is build's block!
person(2)
------分割线------
This is non-static block!
person(1)
This is build's block!
person(2)
这里可以看到,在main函数中,初始化一个类时,执行顺序是:静态域(包括静态属性和静态块)>非静态域>属性>构造器,由此可见,静态块是在类加载的时候执行的,而且在装载生成了.class文件之后,再次定义一个实例对象,静态块是不会被执行的。静态属性和静态块的先后顺序是根据他们在类中定义的先后顺序来决定的。
正是因为静态块只会被执行一次,所以当需要进行一次的初始化操作时,将其放入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) {
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
即执行开始,首先需要找到main方法,但是在执行main方法之前,需要先加载Test,加载Test的过程中发现Test类继承自Base类,因此需要先转着去加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行newTest()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。
static变量
static变量称之为静态变量,静态变量是随着类加载时被完成初始化的,它在内存中仅有一个,且JVM也只会为它分配一次内存,同时类所有的实例都共享静态变量,可以直接通过类名来访问它。但是需要注意,java语法规定:==static是不允许用来修饰局部变量的==。
但是实例变量则不同,它是伴随着实例的,每创建一个实例就会产生一个实例变量,它与该实例同生共死。
所以我们一般在这两种情况下使用静态变量:对象之间共享数据、访问方便。
static方法
static方法称之为静态方法,我们可以通过类名来进行直接调用。由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象。由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能被调用。
在《java编程思想》中这样描述static方法:“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
上述如果有错误的地方,欢迎指正。
参考资料:
https://www.cnblogs.com/dolphin0520/p/3799052.html
https://blog.csdn.net/zhangerqing/article/details/8294039
https://www.cnblogs.com/chenssy/p/3413229.html