1700440930
1700440931
这段程序很简单,输出100嘛!对,确实是100,我们再稍稍修改一下,代码如下:
1700440932
1700440933
public class Client{
1700440934
1700440935
static{
1700440936
1700440937
i=100;
1700440938
1700440939
}
1700440940
1700440941
public static int i=1;
1700440942
1700440943
public static void main(String[]args){
1700440944
1700440945
System.out.println(i);
1700440946
1700440947
}
1700440948
1700440949
}
1700440950
1700440951
注意,变量i的声明和赋值调换了位置,现在的问题是:这段程序能否编译?如果可以编译那输出是多少?还要注意:这个变量i可是先使用(也就是赋值)后声明的。
1700440952
1700440953
答案是:可以编译,没有任何问题,输出是1。对,你没有看错,输出确实是1,而不是100。仅仅调换了一下位置,输出就变了,而且变量i还真是先使用后声明的,难道这世界真的颠倒了?
1700440954
1700440955
这要从静态变量的诞生说起了,静态变量是类加载时被分配到数据区(Data Area)的,它在内存中只有一个拷贝,不会被分配多次,其后的所有赋值操作都是值改变,地址则保持不变。我们知道JVM初始化变量是先声明空间,然后再赋值的,也就是说:
1700440956
1700440957
int i=100;
1700440958
1700440959
在JVM中是分开执行,等价于:
1700440960
1700440961
int i;//分配地址空间
1700440962
1700440963
i=100;//赋值
1700440964
1700440965
静态变量是在类初始化时首先被加载的,JVM会去查找类中所有的静态声明,然后分配空间,注意这时候只是完成了地址空间的分配,还没有赋值,之后JVM会根据类中静态赋值(包括静态类赋值和静态块赋值)的先后顺序来执行。对于程序来说,就是先声明了int类型的地址空间,并把地址传递给了i,然后按照类中的先后顺序执行赋值动作,首先执行静态块中i=100,接着执行i=1,那最后的结果就是i=1了。
1700440966
1700440967
哦,如此而已,那再问一个问题:如果有多个静态块对i继续赋值呢?i当然还是等于1了,谁的位置最靠后谁有最终的决定权。
1700440968
1700440969
有些程序员喜欢把变量定义放到类的底部,如果这是实例变量还好说,没有任何问题,但如果是静态变量,而且还在静态块中进行了赋值,那这结果可就和你期望的不一样了,所以遵循Java通用的开发规范“变量先声明后使用”是一个良好的编码风格。
1700440970
1700440971
注意 再次重申变量要先声明后使用,这不是一句废话。
1700440972
1700440973
1700440974
1700440975
1700440977
编写高质量代码:改善Java程序的151个建议 建议33:不要覆写静态方法
1700440978
1700440979
我们知道在Java中可以通过覆写(Override)来增强或减弱父类的方法和行为,但覆写是针对非静态方法(也叫做实例方法,只有生成实例才能调用的方法)的,不能针对静态方法(static修饰的方法,也叫做类方法),为什么呢?我们先看一个例子,代码如下:
[
上一页 ]
[ :1.70044093e+09 ]
[
下一页 ]