Java修饰符 --- static

一、静态变量和静态方法

  1. 被 static 修饰的变量为类变量,也就是静态变量,可以直接通过类名.变量名引用,也可以通过 new 实例对象调用
  2. 被 static 修饰的方法为类方法,也就是静态方法,可以直接通过类名.方法名引用,也可以通过 new 实例对象调用
  3. 静态变量和静态方法统一属于类的静态资源,是类实例之间共享的,也就是一处变,到处变,是同步的,生命周期长,随类的创建而生,随类的结束而结束

二、静态变量和非静态变量的区别?

  1. 静态变量是属于类的,当且仅当在类初始化的时候加载,在内存只有一个副本,被所有对象(类实例)共享

  2. 非静态变量是对象的,每次创建对象的时候初始化,存在多个副本,各个对象拥有的副本互不影响

  3. 静态变量是存放在方法区的,而非静态变量在堆区

    方法区:存放已经加载的类信息、常量、静态变量以及方法代码的内存区域

    常量池:是方法区的一部分,主要用来存放常量和类中的符号引用等信息

    堆区:用于存放类的对象实例
    栈区:也叫 Java 虚拟栈,由一个一个的栈帧组成的先进后出的栈式结构,栈帧中存放方法运行时产生的局部变量、方法出口等信息,当调用一个方法时,虚拟机栈会创建一个栈帧存放这些数据,当方法完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈帧

三、关于静态方法能否引用非静态资源等问题?

  • 例子:

    public class staticTest {
        
        private int number = 333;
        
        public static void main(String[] args) {
            number = 1;
        }
    
    }
    

    这段代码编译都不会通过,运行的话会报错:无法从静态上下文中引用非静态变量

    原因:

    静态资源属于类,但是是独立于类存在的,存在方法区(静态区),JVM的类加载机制中,静态资源是在类初始化的时候加载,而非静态资源是在类new创建的时候加载,也就是说静态资源的初始化早于非静态资源。所有上述代码中,先执行 main 方法的时候,成员变量 number 还没初始化。

    总结:

    静态方法只能引用静态资源,非静态方法可以引用静态资源和非静态资源

四、静态代码块

用于初始化一个类的时候做操作用的,静态块里的代码只在初始化的时候执行一次

执行顺序(双亲委托加载):

  • 一个类:类内容(静态变量、静态初始化块)=> 实例内容(变量、初始化块、构造器)

  • 继承关系类:父类(静态变量、静态初始化块)=> 子类(静态变量、静态初始化块)=> 父类(变量、初始化块、构造器)=> 子类(变量、初始化块、构造器)

  • 例子:

    public class staticTest {
    
        static {
            number = 333;
            System.out.println(number);
        }
        private static int number;
    
    }
    

    注意:上面代码打印会报错:不能定义之前引用,也就是说:静态代码块对应定义在它之后的静态变量,可以赋值,但是不能访问

五、静态内部类

  • 静态内部类作用:

    1.内部类一般只为其外部类使用

    2.内部类存在外部类的引用,可以直接访问外部类属性

    每个内部类都能单独继承一个接口,而无论外部类是否已经继承该接口(内部类使多重继承的解决方案更加完美)

  • 外部类以对象的方式(创建对象访问)使用内部类,可以访问内部类所有的方法和属性,包括私有方法和属性

    内部类不能访问外部类所在的局部变量,只能访问 final 修饰的局部变量

    在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,为什么?后来想到应该是生命周期的原因,因为方法内定义的变量是局部变量,离开该方法,变量就失去了作用,也就会自动被消除,而内部类却不会离开它所在方法就失去作用

posted @ 2021-10-08 14:19  长歌→  阅读(114)  评论(0编辑  收藏  举报