静态(static)

:::tips

概述

  • static关键字是静态的意思,可以修饰成员方法,成员变量
  • jdk8之后静态变量保存在堆内class对象的尾部
  • jdk8之前存放在方法区静态域中(都不影响使用)

static的特点

  • 被类的所有对象共享
  • 判断是否使用静态关键字的条件
  • 可以通过类名调用(推荐),也可通过对象调用

访问特点

  • 非静态成员方法
    • 能访问静态跟非静态的成员变量
    • 能访问静态跟非静态的成员方法
  • 静态成员方法
    • 能访问静态的成员变量以及方法
    • [静态方法只能访问静态成员]

注意事项

  • 静态变量(类变量)
    • 当需要让某个类的所有对象共享一个类时,可以考虑使用静态变量
    • 静态变量是该类所有对象共享的,而实例变量是每个对象独享的
  • 静态方法(类方法)

    • 当方法不涉及到任何和对象相关的成员,则可以将方法设置为静态方法,提高开发效果
    • 静态方法无this的参数 普通方法隐含this的参数(静态方法不能使用this super关键字)
    • 静态方法中只能访问静态变量或静态方法 :::

      1. public static void main(String[] args) {
      2. //类名.类变量名 推荐
      3. //类变量随着类的加载而创建,所以没有创建对象实例也可以访问
      4. System.out.println(A.name);
      5. //对象名.类变量名
      6. A a = new A();
      7. System.out.println(a.name);
      8. }
      9. }
      10. class A {
      11. public static String name = "静态变量";
      12. }
      public static void main(String[] args) {
      Stu stu1 = new Stu("张三");
      //方法名.静态方法名调用
      stu1.payFee(100.0);
      
      Stu stu2 = new Stu("张三");
      //类名.静态方法名调用
      Stu.payFee(200.0);
      
      Stu.showFee();
      }
      class Stu {
      private static double fee = 0;
      private String name;
      
      //无参带参构造方法
      
      //当方法使用static修饰后,该方法为静态方法
      //静态方法就可以访问静态变量
      public static void payFee(double fee) {
         Stu.fee += fee;
      }
      
      public static void showFee() {
         System.out.println("总学费:" + Stu.fee);
      }
      }
      

      状态修饰符:final(最终态)

      :::tips

      final(最终态)

  • final关键字是最终的意思,可以修饰成员方法,成员变量,类

final修饰的特点:

  • 修饰类:表明该类是最终类,不能被继承
  • 修饰方法:表明该方法是最终方法,不能被重写
  • 修饰变量:表明该变量是常量,不能再次被赋值

final修饰局部变量

  • 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
  • 变量是引用类型:final修饰指的是引用类型的地址值不能改变,但是地址值里的内容可以改变

注意事项

  • final修饰的属性又叫常量
  • final修饰属性在定义时必须赋值,并且不能修改
  • final不能赋值但可实例化对象
  • 如果不是final类但有final方法,则该方法不能重写但可以继承
  • 如果一个类为final类则方法没必要修饰为final方法
  • final不能修饰构造方法(构造器)
  • final跟static搭配使用效率更高,底层编译器做了优化处理
  • final修饰成员变量时必须先赋值或者在构造方法中赋值 :::

    代码块

    :::tips

    概述:

  • 相当于另一种格式的构造器(对构造器的补充机制)可以初始化的操作

  • 如果多个构造器有相同的语句,可以初始化到代码块中,提高代码重用性

注意事项

  • static代码块的作用是对类进行初始化,而且伴随类加载而执行,并且执行一次

如果是普通代码块,每创建一次变量就执行一次

  • 类什么时候被加载
    • 第一次创建对象实例时(new)
    • 创建子类对象实例,父类也会被加载(父类先被加载)
    • 使用类的静态成员时(静态属性静态方法)
    • 在类中运行main方法时
  • 普通代码块在创建对象实例时,会被隐式调用,创建一次就调用一次,如果使用类的静态成员时普通代码并不会执行

    #▲创建一个对象时,在一个类中的调用顺序:

  1. 调用静态代码块和静态属性的初始化(优先级相同,按顺序调用)
  2. 调用普通代码块和普通属性的初始化(优先级相同,按顺序调用)
  3. 调用构造方法

    #▲创建一个子类对象时(继承关系),调用顺序:

  4. 父类静态代码块和静态属性(优先级相同,按顺序调用)

  5. 子类静态代码块和静态属性(优先级相同,按顺序调用)
  6. 父类普通代码块和普通属性初始化(优先级相同,按顺序调用)
  7. 父类构造方法
  8. 子类普通代码块和普通属性初始化(优先级相同,按顺序调用)
  9. 子类构造方法

    静态代码块只能直接调用静态属性和静态方法,普通代码块可以调用任意成员

    ::: ```java public static void main(String[] args) { Movie movie = new Movie(“你好,李焕英”); /*运行结果:
     广告
     好戏开场
     调用一个参数*/
    
    }

class Movie { private String name; private double price;

//不管调用哪个构造器 代码块优先调用
{
    System.out.println("广告");
    System.out.println("好戏开场");
}

public Movie() {
    System.out.println("调用无参");
}

public Movie(String name) {
    System.out.println("调用一个参数");
    this.name = name;
}

public Movie(String name, double price) {
    System.out.println("调用满参");
    this.name = name;
    this.price = price;
}

}

```java
public static void main(String[] args) {
    //创建对象实例时(new)
    //new AA();

    //创建子类对象实例 父类也会被加载 (先调用父类)
    //new BB();

    //使用类的静态成员时(静态属性静态方法)
    int cat = CC.cat;
}

class AA {
    static {
        System.out.println("AA的静态代码被执行");
    }
}

class BB extends AA {
    static {
        System.out.println("BB的静态代码被执行");
    }
}

class CC {
    public static int cat = 0;
    static {
        System.out.println("CC的静态代码被执行");
    }
}

单例设计模式(饿汉式·懒汉式)

:::tips

区别:

  • 两者区别于创建对象的时机不同,饿汉式是类加载就创建,懒汉式是使用才创建
  • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  • 饿汉式存在浪费资源可能,懒汉式使用才创建所以不存在这个问题 :::

    public static void main(String[] args) {
      GirlFriend girlFriend = GirlFriend.getInstance();
      System.out.println(girlFriend);
    }
    /*
      饿汉式单例设计模式
          1.构造器私有化
          2.类的内部创建对象
          3.向外暴露一个静态修饰方法
          [饿汉式可能创建了对象但没有用]
    */
    //只能有一个对象
    class GirlFriend{
      private GirlFriend() {}
    
      private static GirlFriend gF = new GirlFriend();
    
      public static GirlFriend getInstance() {
          return gF;
      }
    }
    
    public static void main(String[] args) {
      Cat instance = Cat.getInstance();
      System.out.println(instance);
    }
    /*
      懒汉式单例设计模式
          1.构造器私有化
          2.创建一个static静态属性对象
          3.提供一个公共的public的static方法,可以返回cat对象
          4.只有使用getInstance()时,才会返回cat对象,
          再次调用时会返回上次创建的cat
          [饿汉式可能创建了对象但没有用]
    */
    //只能创建一个对象
    class Cat {
      private static Cat cat;
    
      private Cat(String name) {}
    
      public static Cat getInstance() {
          if (cat == null) {
              cat = new Cat();
          }
          return cat;
      }
    }