04. static关键字

102 阅读3分钟

[toc]

image.png

01.static的作用

  • static的本质是表明属于类,而非实例。其可以用来修饰:成员变量,成员方法,代码块,内部类等。具体如下所示
    • 修饰成员变量
      • 被static 声明的成员变量属于静态成员变量,其存放在Java内存区域的方法区。
      • static 修饰的成员变量的含义:表明该成员变量属于类,不属于这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。
    • 静态代码块
      • 该类不管创建多少对象,静态代码块只执行一次,对于该类的第一个对象,其执行顺序为:(静态代码块—>非静态代码块—>构造方法)
    • 静态内部类(static修饰类的话只能修饰内部类)
      • 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:1.它的创建是不需要依赖外围类的创建。2.它不能使用任何外围类的非static成员变量和方法。
    • 修饰成员方法
      • 存放在方法区的静态区位置,静态方法无法辨别具体对象,因此只能访问静态的成员变量和静态的成员方法【静态只能访问静态,非静态可以访问静态的也可以访问非静态的】

02.静态变量何时被创建和销毁

静态变量的生命周期就是类的生命周期,考量静态变量的生命周期就是考虑类的生命周期。

  • 静态变量何时创建,进程启动的时候

    • 当我们启动一个app的时候,Android系统会创建相应的进程,此时类被加载,静态变量被分配内存。
  • 静态变量何时销毁,进程死亡 的时候

    • 说明:一般情况下,所有的类都是默认的ClassLoader加载的,只要ClassLoader存在,类就不会被卸载,而默认的ClassLoader生命周期是与进程一致的,而进程结束时,ClassLoader不存在,因此类销毁。

03.静态变量和成员变量的区别

所属不同,导致它的生命周期不同。内存位置不同,导致它的调用不同。使用对象调用本质仍然是通过类名调用。

  • A:所属不同
    • 静态变量属于类,所以也称为类变量
    • 成员变量属于对象,所以也称为实例变量(对象变量)
  • B:内存中位置不同
    • 静态变量存储于方法区的静态区
    • 成员变量存储于堆内存
  • C:生命周期不同
    • 静态变量随着类的加载而加载,随着类的消失而消失
    • 成员变量随着对象的创建而存在,随着对象的消失而消失
  • D:调用不同
    • 静态变量可以通过类名调用,也可以通过对象调用
    • 成员变量只能通过对象名调用

04.用static静态变量潜在性问题

  • 用static静态变量潜在性问题
    • 1.占用内存,并且内存一般不会释放;内存GC是针对堆区进行的垃圾回收,静态变量存放在方法区中,不会被自动回收。
    • 2.出现访问全局静态错误。虽然不会被GC,但是当Android系统检测到某个应用占用了过多内存,或整个系统内存不足时,它可能会激进的直接杀死后台进程来释放内存。如果一个静态变量引用了一个对象(如Activity),在内存不足时系统杀死了应用进程,重新启动后静态变量未被正确初始化,再次访问时会出现NullPointerException,因为该静态对象已经不再存在或数据被丢失。