目录

static 关键字

陈述

首先,一定要注意发音**‘stætɪk**,word天,中文发音不行,英语发音也不行,你还能说啥?Japanese吗?😕……

static 修饰的变量或方式是从属于类的,而没有用static修饰的则是从属于实例对象的。

static可用于:变量、方法、语句块、内部类、导包1

  1. 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。而每创建一个实例就会产生一个实例变量,它与该实例同生共死。
  2. 静态方法:在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。静态方法只能访问所属类的静态字段和静态方法,方法中不能有 thissuper 关键字。
  3. 静态语句块:在类初始化时运行一次。
  4. 静态内部类:可通过类名.静态内部类访问,实际上已经是个独立的类了,但是它能访问外部类的私有静态变量或方法。不能访问外部类的非静态的变量和方法。而非静态内部类依赖于外部类的实例,要通过Outer.Inner inner = outer.new Inner();,其中Outer outer = new Outer();,还可通过Outer.this访问外部类的实例,而this是指的内部类实例自己2
  5. 静态导包:使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低,一般是import static com.xxx.ClassName.*

关于初始化顺序,一定要记住:静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序

先静态后实例,父在子前,静态看顺序

  1. 父类静态变量、静态语句块
  2. 子类静态变量、静态语句块
  3. 父类实例变量、普通语句块
  4. 父类构造方法
  5. 子类实例变量、普通语句块
  6. 子类构造方法

验证

// 静态导入
import java.util.HashMap;

import static java.lang.Math.PI;
import static java.lang.Math.pow;


public class StaticTest {

  private String name = "Hello Static";
  private final String age = "28";

  public static void main(String[] args) {
    StaticTest staticTest = new StaticTest();
    staticTest.println();
    staticTest.print();
    StaticTest.Secret secret = staticTest.new Secret();  // !!! 注意这里的语法 !!!  直接写成 new Secret() 会报错,必须依赖外部类!
    System.out.println(secret.a);
  }

  // 局部内部类
  private void println() {
    class PartInner {
      public PartInner() {
        System.out.println("PartInner.");
        System.out.println("Final Age:" + age);
      }
    }
    PartInner partInner = new PartInner();
    System.out.println(MyMath.circleArea(2));
  }

  // 匿名内部类
  private void print() {
    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>() {
      // 实例语句块
      {
        put(1,2); put(3,4);
      }

      @Override
      public Integer put(Integer key, Integer value) {
        return super.put(key, value);
      }
    };
    System.out.println(map.get(3));
  }

  // (非静态)成员内部类
  private class Secret {
    public int a;
    private int b;
    private String name;  // 同名

    Secret() {
      System.out.println(name);
      name = "Inner Name";
      System.out.println(StaticTest.this.name);
    }
  }

  // 静态(成员)内部类
  static class MyMath {
    public static double circleArea(int r) {
      return PI * pow(r, 2);
    }
  }

}

输出:

PartInner.
Final Age:28
12.566370614359172
4
null
Hello Static
0

思考

能修饰外部类的修饰符只有四种publicdefaultabstractfinal

外部类的上一级程序单位是包,因此它只有两个使用范围:包内和包外,因此它只能用public(表示可以在全局位置使用)和默认修饰符(default,表示只能被同一个包的其他类使用)修饰3

内部类根据其分类又有不同。

  • 成员内部类:就像是类里的成员变量。无条件访问外部类所有成员,对于同名的需要外部类.this.成员进行访问。内部类的修饰符可以是:publicprotecteddefaultprivatestatic
    • 静态内部类:就像是静态成员变量。不依赖外部类。可用访问修饰符修饰4
  • 局部内部类:就像是方法里的局部变量。不能有访问修饰符。只能访问外部类的变量只能是final,方法生命周期的问题。
  • 匿名内部类:就像是方法里的局部变量。不能有访问修饰符。唯一没有构造器的类。

https://cdn.jsdelivr.net/gh/dfface/img0@master/2022/04-25-6go67q.jpg