六、 static、final和常量设计

1. static

  • static 静态的,Java中特殊的关键字
  • 可作用在
    • 变量
    • 方法
    • 匿名方法块
  • 静态变量,类共有成员
    • static变量值依赖于类存在(通过类即可访问),不依赖于对象实例存在
    • 所有的对象实例的静态变量都共享存储在一个共同的空间(栈)
  • static方法
    • 静态方法也无需通过对象来引用,而通过类名可以直接引用
    • 在静态方法中,只能使用静态变量,不能使用非静态变量
    • 静态方法禁止引用非静态方法
  • static块
    • 只在类第一次被加载是调用
    • 执行顺序:static块>匿名块>构造函数
    • 不建议编写代码块,不便于理解

2. 单例模式

  • 又名单态模式,Singleton
  • 限定某一个类在整个程序运行过程中,只能保留一个实例对象在内存空间
  • 单例模式是GoF的23种设计模式中经典的一种,属于创建型模式类型
    • 设计模式:在软件开发过程中,经过验证的,用于解决在特定环境下的、重复出现的、特定问题的解决方案
  • 保证一个类有且只有一个对象
    • 采用static来共享对象实例
    • 采用private构造函数,防止外界new操作
public class Singleton {
    private static Singleton obj = new Singleton(); //共享同一个对象
    private String content;
    
    private Singleton()  //确保只能在类内部调用构造函数
    {
        this.content = "abc";
    }
    
    public String getContent()  {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }   
    
    public static Singleton getInstance()   {
        //静态方法使用静态变量
        //另外可以使用方法内的临时变量,但是不能引用非静态的成员变量
        return obj;
    }
    
    
    public static void main(String[] args) {
        Singleton obj1 = Singleton.getInstance();
        System.out.println(obj1.getContent());  //abc
        
        Singleton obj2 = Singleton.getInstance();
        System.out.println(obj2.getContent());  //abc
        
        obj2.setContent("def");
        System.out.println(obj1.getContent());
        System.out.println(obj2.getContent());
        
        System.out.println(obj1 == obj2); //true, obj1和obj2指向同一个对象
    }

}

3. final

  • 可以用来修饰类、方法、字段
  • final的类不能被继承
  • 父类中final的方法,子类不能改写此方法
  • final的变量,不能被再次赋值
    • 如果是基本类型的变量,不能修改其值
    • 如果是对象实例,那么不能修改其指针(但是可以修改对象内部的值)

4. 常量设计和常量池

常量设计:

  • 常量:一种不会修改的变量
    • Java中没有constant关键字
    • 不能修改 final
    • 不会修改/只读/只要一份 static
    • 方便访问public
  • Java中常量
    • public static final
    • 全大写,以连字符相连
  • 一种特殊的常量:接口内定义的变量默认是常量

常量池:

  • Java为很多基本类型的包装类/字符串都建立常量池
  • 常量池:相同的值只存储一份,节省内存,共享访问
  • 基本类型的包装类
    • Boolean,Byte,Short,Integer,Long,Character,Float,Double
    • Boolean: true, false
    • Byte: -128~127, Character: 0~127
    • Short, Int, Long: -128~127
    • Float,Double:没有常量池
  • Java为常量字符串都建立常量池缓存机制
  • 基本类型的包装类和字符串有两种创建方式
    • 常量式(字面量)赋值创建,放在栈内存(将被常量化)
    • new对象进行创建,放在堆内存(不会被常量化)
  • Integer类
    • 基本类型和包装类比较,将对包装类自动拆箱
    • 对象比较,比较地址
    • 加法+会自动拆箱
  • String类
    • 常量赋值和new创建不是同一个对象
    • 编译器之后优化确定的字符串,并缓存

5. 不可变对象和字符串

不可变对象(Immutable Object)

  • 如何创建不可变对象:
    • immutable对象是不可改变,有改变,请clone/new一个对象进行修改
    • 所有的属性都是final和private的
    • 不提供setter方法
    • 类是final的,或者所有的方法都是final
    • 类中包含mutable对象,那么返回拷贝需要深度clone
  • 优点:
    • 只读,线程安全
    • 并发读,提高性能
    • 可以重复使用
  • 缺点
    • 制造垃圾,浪费空间
  • 字符串是Java使用最多的类,是一种典型的不可变对象
    • String两种定义:常量赋值(栈分配内存),new对象(堆分配内存)
    • 字符串内容比较:equals方法
    • 是否指向同一个对象:指针比较==
    • 修改字符串可采用StringBuffer(同步,线程安全,修改快速)和StringBuilder(不同步,线程不安全,修改更快)

你可能感兴趣的:(六、 static、final和常量设计)