平时在项目中可能经常会用到一些常量,一般都定义成static final的,有时候可能会突然想到,到底staitc,final,static final定义的变量到底有什么关系呢?
通过以下例子一起看一下:
/**
* @Description: 变量定义类
* @Author: yuhua
* @Date: 2018/12/7
*/
public class FinalStaticDemo {
public final double aDouble= Math.random();
public static double bDouble = Math.random();
}
/**
* @Description: static与final修饰变量详解测试类
* @Author: yuhua
* @Date: 2018/12/7
*/
public class FinalStaticTest {
/**
* final跟static的代码表现总结
* 1.final的变量在定义初始化的取值与1、2条输出值一样。
* 若是在期间修改( myClass.aDouble=11.00;)final的值会报错:Error:(7, 16) java: 无法为最终变量aDouble分配值。
* 2.通过对static变量定义赋初值输出,与先后两次修改static的值,其值都在变化。
* 3.我们观察输出两个对象的final变量值是不同的,而在同一个阶段(过程中未发生修改),两个static的变量值是相同的。
*
* final跟static的总结
* 1.由代码表现1,可以得到final的一经赋初值自始至终都不会改变,在代码过程中不允许对final的值做修改。
* 2.static得变量在定义赋初值后,在以后的代码中可以被修改,只要是改一次就变一次,。
* 3.static变量跟final变量在内存中分布不同,final变量在堆内存中,两个对象各有一块且有自己的初值,而static在data seg区域只存在一份值(共享)。
*
* 最终结论,通过实验我们可以得出:
* 1.final变量在赋初值后,在后期过程中不可被改变。
* 2.static变量在赋初值后,每次修改都可以改变,且在方法区中仅有一份,两个对象共享信息。
* 3.static final定义的常量,在dataseg区域存在一份不可修改的常量值。
*
* 另外,final修饰有如下特征:
* 1.final修饰的类不能被继承
* 2.final修饰的方法不能被子类重写
* 3.final修饰变量,变量不能被修改
*/
public static void main(String[] args) {
1. FinalStaticDemo finalStaticDemo = new FinalStaticDemo();
2. FinalStaticDemo finalStaticDemo1 = new FinalStaticDemo();
3. System.out.println("FinalStaticDemo类定义final变量时候取值: "+ finalStaticDemo.aDouble);
4. System.out.println("FinalStaticDemo1类定义final变量时候取值: "+ finalStaticDemo1.aDouble);
5. System.out.println("FinalStaticDemo类定义static变量时候取值: "+ finalStaticDemo.bDouble);
6. System.out.println("FinalStaticDemo1类定义static变量时候取值: "+ finalStaticDemo1.bDouble);
//第一次修改static值
7. finalStaticDemo.bDouble=Math.random();
//final变量不能被修改,只是值不能被再分配,你若是强行修改他就报错:Error:(36, 32) java: 无法为最终变量aDouble分配值
// finalStaticDemo.aDouble=11.00;
8. System.out.println("1 第一次myClass final: "+ finalStaticDemo.aDouble);
9. System.out.println("2 第一次myClass1 final: "+ finalStaticDemo1.aDouble);
10. System.out.println("3 第一次myClass static: "+ finalStaticDemo.bDouble);
11. System.out.println("4 第一次myClass1 static: "+ finalStaticDemo1.bDouble);
//第二次修改static值
12. finalStaticDemo1.bDouble=Math.random();
13. System.out.println("5 第二次myClass static: "+ finalStaticDemo.bDouble);
14. System.out.println("6 第二次myClass1 static: "+ finalStaticDemo1.bDouble);
}
}
输出值:
FinalStaticDemo类定义final变量时候取值: 0.1331466337681967
FinalStaticDemo1类定义final变量时候取值: 0.6718066536403038
FinalStaticDemo类定义static变量时候取值: 0.7568583648875984
FinalStaticDemo1类定义static变量时候取值: 0.7568583648875984
1 第一次myClass final: 0.1331466337681967
2 第一次myClass1 final: 0.6718066536403038
3 第一次myClass static: 0.8134530385938469
4 第一次myClass1 static: 0.8134530385938469
5 第二次myClass static: 0.4914602180950418
6 第二次myClass1 static: 0.4914602180950418
过程内存分析图:为了画图方面,我把finalStaticDemo看作c1,finalStaticDemo2看作c2,aDouble看作a,bDouble看作b。
1、运行到第1句后,内存分布状态:
2、执行完第二句后,内存分布状态(注意看方法区,这时候里面就一份静态变量值为data,final值未变化):
3.执行完第7句,内存分布状态(注意看方法区中的静态变量,这时候已经被修改了,起初final变量仍未变化):
上面讲清楚了static,final,自然而然static final定义的变量就很简单了,被它定义过的变量是在方法区中初始值赋值后不可修改的一块值空间。
对于内存分析不是很明白的可以再回顾一下这一篇文章https://blog.csdn.net/Myuhua/article/details/81385609