一. static关键字的基本用法

1. static关键字基本概念

被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。

2. static关键字修饰类

static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。

  1. package com.yue.Static;
  2. public class StaticClass {
  3. // static关键字修饰内部类
  4. public static class InnerClass {
  5. InnerClass() {
  6. System.out.println("============= 静态内部类=============");
  7. }
  8. public void InnerMethod() {
  9. System.out.println("============= 静态内部方法=============");
  10. }
  11. }
  12. public static void main(String[] args) {
  13. // 直接通过StaticTest类名访问静态内部类InnerClass
  14. InnerClass inner = new StaticClass.InnerClass();
  15. // 静态内部类可以和普通类一样使用
  16. inner.InnerMethod();
  17. }
  18. }

3. static关键字修饰方法

  1. package com.yue.Static;
  2. public class StaticMethod {
  3. public static void test() {
  4. System.out.println("============= 静态方法=============");
  5. };
  6. public static void main(String[] args) {
  7. //方式一:直接通过类名
  8. StaticMethod.test();
  9. //方式二:
  10. StaticMethod fdd=new StaticMethod();
  11. fdd.test();
  12. }
  13. }

4. static关键字修饰变量

被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量属于这个类,而不属于对象。

  1. package com.yue.Static;
  2. public class StaticVar {
  3. private static String name = "StaticVar";
  4. public static void main(String[] args) {
  5. //直接通过类名
  6. System.out.println(StaticVar.name);
  7. }
  8. }

5. static关键字修饰代码块

静态代码块在类第一次被载入时执行,类初始化的顺序:

  • 父类静态变量
  • 父类静态代码块
  • 子类静态变量
  • 子类静态代码块
  • 父类普通变量
  • 父类普通代码块
  • 父类构造函数
  • 子类普通变量
  • 子类普通代码块
  • 子类构造函数
    父类:
    ```java package com.yue.Static.Example;

public class Father {

  1. // 父类静态代码块
  2. static {
  3. System.out.println("Father static");
  4. }
  5. // 父类构造函数
  6. public Father() {
  7. System.out.println("Father constructor");
  8. }

}

  1. <a name="rYB6d"></a>
  2. ##### 子类:
  3. ```java
  4. package com.yue.Static.Example;
  5. public class Son extends Father {
  6. // 静态代码块
  7. static {
  8. System.out.println("Son static");
  9. }
  10. // 构造方法
  11. public Son() {
  12. System.out.println("Son constructor");
  13. }
  14. public static void main(String[] args) {
  15. new Son();
  16. }
  17. }

结果:

图片.png**

二. 深入分析static关键字

特点:

  1. static是一个修饰符,用于修饰成员。(成员变量,成员函数)static修饰的成员变量 称之为静态变量或类变量。
  2. static修饰的成员被所有的对象共享。
  3. static优先于对象存在,因为static的成员随着类的加载就已经存在。
  4. static修饰的成员多了一种调用方式,可以直接被类名所调用,(类名.静态成员)。
  5. static修饰的数据是共享数据,对象中的存储的是特有的数据。

    成员变量和静态变量的区别:

  6. 生命周期的不同:

    1. 成员变量随着对象的创建而存在随着对象的回收而释放。
    2. 静态变量随着类的加载而存在随着类的消失而消失。
  7. 调用方式不同:
    1. 成员变量只能被对象调用。
    2. 静态变量可以被对象调用,也可以用类名调用。(推荐用类名调用)
  8. 别名不同:
    1. 成员变量也称为实例变量。
    2. 静态变量称为类变量。
  9. 数据存储位置不同:

    1. 成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
    2. 静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

      静态使用时需要注意的事项:

  10. 静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)

  11. 静态方法中不可以使用this或者super关键字。
  12. 主函数是静态的。

三. 面试题

1.下列代码输出什么结果?

  1. package com.yue.Static;
  2. public class StaticTest {
  3. static {
  4. _i = 20;
  5. }
  6. public static int _i = 10;
  7. public static void main(String[] args) {
  8. System.out.println(_i);
  9. }
  10. }

答案:

10.
图片.png

解析:

理解所需的前置条件:

条件一:静态变量如何初始化
答案:直接赋值/用代码块/静态函数返回值

  1. static {
  2. _i = 10;
  3. }
  4. public static int _i;

等价于
public static int _i = 10;

条件二:JDK如何处理static块
答案:根据先后顺序

  1. public static int _i;
  2. static {
  3. _i = 10;
  4. }
  5. public static void main(String[] args) {
  6. }
  7. static {
  8. _i = 20;
  9. }

等价于

  1. public static int _i;
  2. public static void main(String[] args) {
  3. }
  4. static {
  5. _i = 10;
  6. _i = 20;
  7. }

根据条件一得出:
  1. static {
  2. _i = 10;
  3. }
  4. public static int _i;

等价于

  1. public static int _i = 10;

根据条件二得出:
  1. static {
  2. _i = 20;
  3. }
  4. public static int _i = 10;

等价于

  1. static {
  2. _i = 20;
  3. _i = 10;
  4. }
  5. public static int _i;

最终得出:

_i = 10;

2. 为什么static的变量是唯一的,怎么实现的?

答案:

static声明的类存在方法区,而不是堆。
static声明变量/方法/类的不生成对象副本。