Fork me on Gitee

以不变应万变:final关键字和不变形

以不变应万变:final关键字和不变形

什么是不变形(Immutable)

  • 如果对象在被创建后,状态就不能被修改,那么它就是不可变的。

    • 例如:person对象,age和name都不能再变
    • 具备不变性的对象一定是线程安全的,我们不需要对其采取任何额外的安全措施,也能保证线程安全。
public class Person {
    public final int age = 18;
    public final String name = "Alice";

}

在其他类中,只可以读取,而不可以赋值。

/**
 * 测试final能否被修改
 */
public class TestFinal {
    public static void main(String[] args) {
        Person person = new Person();
        person.age = 178;
    }
}

final的作用

3种用法:修饰变量、方法、类

image-20240304210643231

  • 属性被声明为final后,该变量则只能被赋值一次。且一旦被赋值,final的变量就不能再被改变,如论如何也不会变。

赋值时机

image-20240304210833041

public class FinalVariableDemo {
    private final int a;

    /**
     * 构造函数中赋值
     * @param a
     */
    public FinalVariableDemo(int a){
        this.a = a;
    }
	
    // 代码块中赋值
    {
        a=7;
    }
    
}

image-20240304211059738

public class FinalVariableDemo {
    // 第一种,等号后面赋值
    private static final int a;

 
	// 第二种:静态代码块赋值
    static {
        a=7;
    }

}

image-20240304211601613

public class FinalVariableDemo {
//    private static final int a;


    void testFinal(){
        final  int b;
        b = 5;
        int c = b;
    }



}

注意点

final修饰方法

  • 构造函数不 允许final修饰

  • 不可被重写,也就是不能被override,.即便是子类有相同名字的方法,那也不是override,这个和static方法是一个道理。

  • 引申:static方法不能被重写

final修饰类

  • final修饰类不可被继承,例如典型的String类就是final

总结

  • final修饰对象的时候,只是对象的引用不可变,而对象本身的属性是可以变化的
  • final使用原则:良好的编程习惯

不变性和final的关系

  • 不变形并不意味着,简单地用final修饰是不可变。
    • 对于基本数据类型
  • 如何利用final实现对象不可变?<不对>

总结出,满足以下条件时,对象才是不可变的

  • 对象创建后,其状态就不能改变
  • 所有属性都是final修饰的
  • 对象创建过程中没有发生溢出

把变量写在线程内部——栈封闭

  • 在方法里新建的局部变量,实际上是存储在每个线程私有的栈空间,而每个栈的占空间是不能被其他线程所访问到的,所以不会有线程安全问题。这就是著名的“栈封闭”技术,是“线程封闭”技术的一种情况。
posted @ 2024-03-04 21:45  shine-rainbow  阅读(10)  评论(0编辑  收藏  举报