• java的static关键字及类加载顺序


    Java中static可以修饰类、变量、方法甚至可以构成静态块,让我们来了解下它们各自的使用以及加载顺序吧。

    基本用法

    static关键字修饰类

    java里面用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。

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

    如果没有用static修饰InterClass,则只能new 一个外部类实例。再通过外部实例创建内部类。

    static关键字修饰方法

    修饰方法的时候,其实跟类一样,可以直接通过类名来进行调用:

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

    static关键字修饰变量

    被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量是属于这个类的,而不是属于是对象,没有被static修饰的成员变量叫做实例变量,说明这个变量是属于某个具体的对象的。

    我们同样可以使用上面的方式进行调用变量:

    public class StaticVar {
        private static String name="java技术栈";
    
        public static void main(String[] args) {
            //直接通过类名
            StaticVar.name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    static关键字修饰代码块

    静态代码块在类第一次被载入时执行,在这里主要是想验证一下,类初始化的顺序。

    父类静态变量
    父类静态代码块
    
    子类静态变量
    子类静态代码块
    
    父类普通变量
    父类普通代码块
    父类构造函数
    
    子类普通变量
    子类普通代码块
    子类构造函数
    //首先我们定义一个父类
    public class Father {
        // 父类静态变量
        public static String str1 = "father static str";
        // 父类普通变量
        public String str2 = "father common str";
        // 父类静态代码块
        static {
            System.out.println("father static block");
        }
        // 父类普通代码块
        {
            System.out.println("father common block");
        }
        // 父类构造方法
        public Father() {
            System.out.println("father constructor");
        }
    }
    
    //然后定义一个子类
    public class Child extends Father {
        // 子类静态变量
        public static String str1 = "child static str";
        // 子类普通变量
        public String str2 = "child common str";
        // 子类静态代码块
        static {
            System.out.println("child static block");
        }
        // 子类普通代码块
        {
            System.out.println("child common block");
        }
        // 子类构造方法
        public Child() {
            System.out.println("child constructor");
        }
    }
    
    // 测试
    public static void main(String[] args) {
            new Child();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    输出为:

    father static block
    child static block
    father common block
    father constructor
    child common block
    child constructor
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    原理讲解

    3wb8Tx.png

    上图为jvm运行时数据区,静态变量存放在方法区中,并且是被所有线程所共享的。

    方法区中包含的都是在整个程序中永远唯一的元素,如类信息、static变量等。

    举例

    定义一个类,包含静态变量、静态方法。

    public class Person{
        //静态变量
        static String firstName;
    
        String lastName;
    
        public void showName(){
            System.out.println(firstName+lastName);
        }
    
        //静态方法
        public static void viewName(){
          System.out.println(firstName);
        }
    
        public static void main(String[] args) {
            Person p =new Person();
            Person.firstName = "张";
            p.lastName="三";
            p.showName();
    
            Person p2 =new Person();
            Person.firstName="李";
            p2.lastName="四";
            p2.showName();
        }
    }
    //输出。张三、李四
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    从内存的角度看一下:
    3wxuUs.png

    从上面可以看到,我们的方法在调用静态方法、变量的时候,是从方法区调用的,但是调用普通变量是从堆内存中调用的,堆内存中的成员变量lastname是随着对象的产生而产生,随着对象的消失而消失。静态变量是所有线程共享的,所以不会消失。


    小结

    特点

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

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

    1. 生命周期的不同:

    成员变量随着对象的创建而存在随着对象的回收而释放。

    静态变量随着类的加载而存在随着类的消失而消失。

    1. 调用方式不同:

    成员变量只能被对象调用。

    静态变量可以被对象调用,也可以用类名调用。(推荐用类名调用)

    1. 别名不同:

    成员变量也称为实例变量。

    静态变量称为类变量。

    1. 数据存储位置不同:

    成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。

    静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

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

    1. 静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)
    2. 静态方法中不可以使用this或者super关键字。
    3. 主函数是静态的
  • 相关阅读:
    使用 docker buildx 构建跨平台镜像 (QEMU/buildx/build)
    MySQL 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)
    【数据结构】归并排序和计数排序(排序的总结)
    鸿蒙tabbar ArkTS
    小熊派-FreeRTOS-点灯学习过程-20221029
    Apollo(阿波罗)分布式配置中心
    3D RPG Course | Core 学习日记三:Navigation智能导航地图烘焙
    将“192.2.0.1“转换为“192.002.000.001“
    【知识图谱】Louvain、LPA等5类经典社区发现算法 Python 实战
    Unity之ShaderGraph如何实现触电电流效果
  • 原文地址:https://blog.csdn.net/guodong54/article/details/127901916