文章目录
1. 什么是不变性
- 不可变的对象,演示其他类无法修改这个对象,public也不行
- 案例演示
2. final的作用
3. 3种用途:修饰变量、方法、类
3.1 修饰变量
public class Person {
final int age = 18;
final String name = alice;
String bag = "computer";
public static void main(String[] args) {
final Person person = new Person();
person.bag = "book"; // 可以修改类的内容
// person = new Person(); // 不能重新引用
}
}
1. 类中的final变量属性
2. 类中的staic final属性
/**
* 描述: 演示final变量
*/
public class FinalVariableDemo {
// 1.可以直接赋值
private static final int a;
// 2.或是在静态代码块中赋值
// static {
// a = 7;
// }
}
方法中的final变量
/**
* 描述: 演示final变量
*/
public class FinalVariableDemo {
// void testFinal() {
// final int b = 7;
// int c = b;// 确保b使用时,是有赋值的
// }
}
3.2 修饰方法
- 子类理论上是可以定义与父类相同的静态方法,但是属于各自类,没有继承关系
3.3 修饰类
4. 注意点
5. 不变性和final的关系
5.1 如何确保类不可变
5.2 栈封闭
package immutable;
/**
* 描述: 演示栈封闭的两种情况,基本变量和对象 先演示线程争抢带来错误结果,然后把变量放到方法内,情况就变了
*/
public class StackConfinement implements Runnable {
int index = 0;
public void inThread() {
// 方法内的变量,不共享,是安全的
int neverGoOut = 0;
// synchronized (this) {
for (int i = 0; i < 10000; i++) {
neverGoOut++;
}
// }
System.out.println("栈内保护的数字是线程安全的:" + neverGoOut);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
index++;
}
inThread();
}
public static void main(String[] args) throws InterruptedException {
StackConfinement r1 = new StackConfinement();
Thread thread1 = new Thread(r1);
Thread thread2 = new Thread(r1);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(r1.index);
}
}
6. 常见面试题
示例1:
- 因b被final修饰,故,是不变的常量,编译期就确定的,这样,c能发现b,直接计算出字符串值
wukong2
,发现常量池中有,就直接指向a指向的常量,因此,地址一样 - 但,d不同,在编译器无法识别,只有在运行时确定,e会在运行时在堆上创建一个指向
wokong2
的引用,因此,地址不同
示例2:
- 获取方法的值,编译器不会做优化,只有在运行期才能拿到