Java Static成员的加载
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Static成员的加载相关的知识,希望对你有一定的参考价值。
【内容简介】
本文将讨论Java中被static修饰符修饰的成员变量的加载方式。
【能力需求 】
至少已经完整的掌握了Java的语法基础,掌握了面向对象中类、对象、属性、方法的概念,了解构造方法,了解类的属性的默认值。
【正文】
先看代码,并预测运行结果
public class StaticDemo { /** 成员变量 */ public static StaticDemo demo = new StaticDemo(); /** 成员变量 */ public static int i1; /** 成员变量 */ public static int i2 = 0; /** 构造方法 */ public StaticDemo() { i1++; i2++; } public static void main(String[] args) { System.out.println(i1); System.out.println(i2); } }
OK,代码完成,答案是:i1的值为1,i2的值为0 (请用鼠标框选这里的蓝色位置查看答案)
可能存在的误解:
一眼看过去,貌似i1和i2的值是一样的,因为它们都是成员变量,int型的成员变量的默认值就是0,所以i1和i2的声明看起来是等效的,当然,在一般情况下,这样的理解并没有错,但是,实际运行情况却不同!
众所周知,用static修饰的成员将具有最优先加载的权利,优先于一切非static成员之前,当然也包括各种构造方法,所以,这样的成员在内存的堆(Heap)空间内是无法存放的,它们会被存储到专门的静态域。
static成员加载的顺序是:static成员会依次从上至下的加载,而且加载时,先加载全部static成员的数据类型,并赋以默认值,然后再回过头来运行每个static成员的赋值语句!
所以,上面的代码运行流程是:
- 从上至下的加载,所以依次运行第3、5、7行的声明部分
- 加载StaticDemo demo成员变量(对象),目前不运行赋值语句,基于它是复合数据类型,则默认值为null
- 加载int i1成员变量,目前不运行赋值语句,基于它是基本数据类型(又名简单数据类型)的int类型,则默认值为0
- 加载int i2成员变量,同上,默认值为0
- 加载static成员的数据类型完成,回过头来,从上至下依次完成第3、5、7行的赋值部分
- 运行第3行的赋值语句,则调用第10行开始的构造方法,运行完成后,则i1=1, i2=1
- 运行第5行的赋值语句,然而这行没有赋值语句,则跳过,则i1的值依然为1,i2没有发生变化依然为1
- 运行第7行的赋值语句,i2的值被赋值为0
说到底,其实i2是被赋值了2次的,起初默认值为0,第1次赋值出现在构造方法中,值被改变为1,第2次出现在第7行,值被改变为0。
测试:
可以尝试把第3行语句public static StaticDemo demo = new StaticDemo();移动到第7行public static i2 = 0;之后,再次运行,发现结果都是1,即可印证刚才的解释。
最后,附加一些废话:
由于static成员不是属于任何一个对象的,那么就不应该使用传统的对象名.属性名进行访问(这样的语法是允许的,但是完全不推荐,如果不想被人鄙视,就不要这样做),由于它们是在某一个类中声明的,所以访问它们的语法是类名.属性名,当然,调用被static修饰的方法也是使用一样的语法。
另外,static成员只有1个值,假设Demo类存在static修饰的成员变量int x = 10,然后Demo类被创建了2个对象分别是demo1和demo2,其实Demo.x、demo1.x、demo2.x都是访问到的相同的变量,不管由哪种语法尝试改变它的值,始终都是改的同一个,如果要打印出来,将显示最后一次被修改的值。
【小结】
static成员会依次从上至下的加载,而且加载时,先加载全部static成员的数据类型,并赋以默认值,然后再回过头来运行每个static成员的赋值语句
如果本文有不足或者错误的地方,欢迎随时指出,如需转载,请注明出处,Thank you !
以上是关于Java Static成员的加载的主要内容,如果未能解决你的问题,请参考以下文章