2、静态字段和静态方法
# static关键字
在类中,static 可以修饰变量和方法。
static修饰的变量称为静态成员变量,也称为类变量。
static修饰的方法称为静态方法,也称为类方法。
static修饰的代码块称为静态代码块,也称为static块。
eg:
public class HelloCoder {
static String name = "HaC"; //静态变量
static //静态代码块
{
System.out.println(name);
}
//静态方法
public static void printName(){
System.out.println(name);
}
}
static的生命周期和类相同,所以说,static和对象没什么关系,和类有关系。
# static的用途
一句话描述就是:在没有创建对象的情况下调用方法或者变量。
# static变量
静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化。
非静态变量是只有在对象创建的时候才能操作。
static成员变量初始化顺序按照定义的顺序来进行初始化
# static方法
static方法也是属于类,不依赖对象,所以static方法是没有this
(this表示本实例对象) ,虽然对象也能访问static方法。
因为没有
this
,所以静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法和静态成员变量。
毕竟普通方法是属于对象的,你静态方法是属于类的,类是优先比对象加载的,类调用对象的东西,对象还没加载,这就会有问题,所以静态方法中不能访问非静态成员方法和非静态成员变量,反过来就可以。
静态方法可以直接通过 类名.静态方法
直接访问。
# static块
static块的作用是为了在Java程序执行前优先执行,提升程序的性能。
静态初始化块可以置于类中的任何地方,类中可以有多个静态初始化块。 在类初次被加载时,会按照静态初始化块的顺序来执行每个块,并且只会执行一次。
切记:static是不允许用来修饰局部变量
为什么呢?
因为static是表示全局的,共同使用的;你局部变量只是给局部方法使用的。记住这是Java规定的就行。
eg:
public class HelloCoder {
static String name = "HaC"; //静态变量
static //静态代码块
{
System.out.println(name);
}
//静态方法
public static void printName() {
System.out.println(name);
// test(); //报错,静态方法不能调用非静态方法
}
public void test() { //平台方法
printName(); //非静态方法可以调用静态方法
// static int age = 1; //报错,static是不允许用来修饰局部变量
}
public static void main(String[] args) { //main方法也是一个静态方法
HelloCoder helloCoder = new HelloCoder();
helloCoder.printName(); //也可以使用对象访问静态方法
HelloCoder.printName(); //建议使用这种方法访问
}
}
以上在类加载的时候,首先会执行静态代码块,执行System.out.println(name);
输出:
HaC
HaC
HaC
# 类加载的顺序
上一章节中学了继承。是先执行父类的构造方法,在执行子类的构造方法。
那如果引入static代码块、普通代码块呢?
eg:
class HelloA {
public HelloA() {
System.out.println("A init");
}
{
System.out.println("I’m A class");
}
static {
System.out.println("static A");
}
}
class HelloB extends HelloA {
static {
System.out.println("static B");
}
public HelloB() {
System.out.println("B init");
}
{
System.out.println("I’m B class");
}
public static void main(String[] args) {
new HelloB();
}
}
输出:
static A static B I’m A class A init I’m B class B init
Java在执行的时候,是有顺序的,在 new Object()
的时候,会执行构造方法,但是在子类、父类都有构造方法的时候,还有静态方法的时候,它的执行顺序是这样的:
- 父类的静态代码块
- 子类的静态代码块
- 父类的普通代码块
- 父类的构造方法
- 子类的普通代码块
- 子类的构造方法
static 和对象无关,类加载,static就加载,那肯定是优先执行static的。
进入main方法,new 对象 时 发现继承父类,优先执行父类,发现父类还有代码块,优先执行代码块
等到分配了内存,再去执行构造方法。
最后回到子类。