Static修饰符

Static修饰符

个人总结:static有五种使用场景,在这篇博客当中我会详细的介绍.

1.修饰属性

2.修饰方法

3.修饰代码块

4.修饰类

5.修饰导入

6.初始化顺序


修饰静态属性

属性的分类:

静态属性:

类加载的时候初始化,而且只有一次

经典应用:产生唯一性自增ID、单例模式

初始化时机:类加载的时候

非静态属性:

类创建对象的初始化,可以初始化多次

初始化时机:调用构造方法创建对象的时候

我们通过产生唯一性自增ID的代码来理解下静态属性的特点,首先我们先来看一个代码demo01:

public class StaticField {
   //非静态属性
    private int id;
   //构造方法
    public StaticField() {
        ++id
    }
  public static void main(String[] args) {
      StaticField s1 = new StaticField();
      StaticField s2 = new StaticField();
      System.out.println(s1.id);
      System.out.println(s2.id);
  }
}
结果: 1 1

如果你认为结果是s1=1,s2=2那么是错误的,通过上面的结果我们可以得出两个结论:

1.非静态属性访问方式,先创建对象,再访问(demo01中的id属性)

2.非静态属性初始化的时机是当调用构造方法创建对象时,如果多次调用构造方法

public StaticField() {
  ++id
}

则非静态属性值会重新赋值(重置),并不会叠加.

通过demo01我们了解到非静态属性的结论后,我们现在来看看代码demo02:

public class StaticField {
   //非静态属性
    private int id;
   //静态属性
    private static int guid;
   //构造方法啊
    public StaticField() {
       this.id = guid++;
    }
  public static void main(String[] args) {
     //静态属性访问方式,类名.属性名
     //注意:如果访问的静态属性就是本类中则类名可以省略
      System.out.println(StaticField.guid);
      System.out.println(guid);
     //非静态属性方法,先创建对象再访问
      StaticField s1 = new StaticField();
      StaticField s2 = new StaticField();
      System.out.println(s1.id);
      System.out.println(s2.id);
  }
}
结果: 1 2

在demo02当中我新定义了一个静态属性guid我的目的是希望能实现产生唯一性自增ID,结果也达到了我的预期,那么通过demo02我们可以得出的结论有:

1.静态属性访问方式,类名.属性名(demo02中的guid属性)

2.非静态属性方法,先创建对象再访问(denmo02中的id属性)

3.静态属性初始化的时机是类加载的时候,而且只执行一次,即不会重置

public StaticField() {
     this.id = ++guid;
}

既然guid不会被重置,所以每一次创建对象的时候都会使它++guid自增,那么id也会对应的被guid赋值,从而间接的达到了产生唯一性自增ID的效果

修饰静态方法

方法分类:

非静态方法

非静态方法可以直接调用任何方法

静态方法:

静态方法只能直接调用静态方法,调用非静态方法前需要创建对象

demo03

public class StaticMethod {
    public static void main(String[] args) {
        method2();

        StaticMethod demo = new StaticMethod();
        demo.method1();
    }

    public void method1() {

    }

    public static void method2() {

    }
}

通过demo03的代码我们可以得出如下结论:

静态方法可以直接通过类名.方法名方式调用,例如:Math.max(3,4)

非静态方法不能直接通过类名调用,它必须创建对象,然后再调用.

静态方法可以直接调用其他静态方法,但是不能直接调用非静态方法,调用非静态方法必须创建对象,然后再调用.比如说mian方法就是典型的例子

非静态方法可以直接调用静态方法或者非静态方法

修饰静态代码块

代码块分类:

非静态代码块:

会在每次构造方法调用之前优先执行调用

静态代码块:

在类加载的时候就执行并且只执行一次

使用场景:一般做系统的初始化工作,例如:建立数据库连接,加载大型资源配置文件...

初始化时机:类加载的时候

demo04:

public class StaticBlock {
   {
        System.out.println("普通代码块...");
    }
  
  static{
        System.out.println("静态代码块...");
    }
  
   public StaticBlock() {
        System.out.println("StaticBlock的构造方法...");
    }

   public static void main(String[] args) {
        StaticBlock staticBlock1 = new StaticBlock();
        StaticBlock staticBlock2 = new StaticBlock();
    }
}
结果:
静态代码块...
普通代码块...
StaticBlock的构造方法...
普通代码块...
StaticBlock的构造方法...

通过demo4我们可以得出以下结论:

1,

普通代码块,调用的时机是每次调用构造方法创建对象之前都会自动优先调用(一次或者多次)

注意⚠️: 普通代码块一般不使用,因为普通代码块中的代码可以直接整合到构造方法即可

静态代码块,当类加载的时候就执行,而且有且只有一次

注意⚠️: 静态代码块非常有用!我们可以利用它来完成很多费事费力,需要消耗大量系统资源的操作(前置完成)

例如: 建立数据库连接池,建立数据库连接,加载大型资源配置文件....

修饰静态类

静态内部类
非静态内部类依赖于外部类的实例,而静态内部类不需要。

public class OuterClass {
    class InnerClass {
    }

    static class StaticInnerClass {
    }

    public static void main(String[] args) {
        // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
        OuterClass outerClass = new OuterClass();
        InnerClass innerClass = outerClass.new InnerClass();
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }
}

静态内部类不能访问外部类的非静态的变量和方法。

修饰静态导入

静态导入

例如:import static xxx.xxx.xxx.*注意.*指定的是导入这个类下的所有静态方法

这样在业务开发的时候可以简化代码.

初始化顺序

静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。

public static String staticField = "静态变量";
static {
    System.out.println("静态语句块");
}
public String field = "实例变量";
{
    System.out.println("普通语句块");
}

最后才是构造函数的初始化。

public InitialOrderTest() {
    System.out.println("构造函数");
}

存在继承的情况下,初始化顺序为:

父类(静态变量、静态语句块)
子类(静态变量、静态语句块)
父类(实例变量、普通语句块)
父类(构造函数)
子类(实例变量、普通语句块)
子类(构造函数)

posted @ 2022-03-19 15:55  JanoCode  阅读(26)  评论(0)    收藏  举报