建议32: 静态变量一定要先声明后赋值

这标题看着让人很纳闷,什么叫做变量一定要先声明后赋值?Java中的变量不都是先声明后使用的吗?难道还能先使用后声明?能不能暂且不说,我们先来看一个例子,代码如下:

 public class Client {
public static int i=1;
static{
i=100;
}
public static void main(String[] args) {
System.out.println(i);
}
}

这段程序很简单,输出100嘛!对,确实是100,我们再稍稍修改一下,代码如下:

 public class Client {
static {
i = 100;
}
public static int i = 1; public static void main(String[] args) {
System.out.println(i);
}
}

注意,变量i的声明和赋值调换了位置,现在的问题是:这段程序能否编译?如果可以编译那输出是多少?还要注意:这个变量i可是先使用(也就是赋值)后声明的。

答案是:可以编译,没有任何问题,输出是1。对,你没有看错,输出确实是1,而不是100。仅仅调换了一下位置,输出就变了,而且变量i还真是先使用后声明的,难道这世界真的颠倒了?

这要从静态变量的诞生说起了,静态变量是类加载时被分配到数据区(Data Area)的,它在内存中只有一个拷贝,不会被分配多次,其后的所有赋值操作都是值改变,地址则保持不变。我们知道JVM初始化变量是先声明空间,然后再赋值的,也就是说:

int i=100;
在JVM中是分开执行,等价于:
int i; //分配地址空间
i=100; //赋值

静态变量是在类初始化时首先被加载的,JVM会去查找类中所有的静态声明,然后分配空间,注意这时候只是完成了地址空间的分配,还没有赋值,之后JVM会根据类中静态赋值(包括静态类赋值和静态块赋值)的先后顺序来执行。对于程序来说,就是先声明了int类型的地址空间,并把地址传递给了i,然后按照类中的先后顺序执行赋值动作,首先执行静态块中i=100,接着执行i=1,那最后的结果就是i=1了。

哦,如此而已,那再问一个问题:如果有多个静态块对i继续赋值呢?i当然还是等于1了,谁的位置最靠后谁有最终的决定权。

有些程序员喜欢把变量定义放到类的底部,如果这是实例变量还好说,没有任何问题,但如果是静态变量,而且还在静态块中进行了赋值,那这结果可就和你期望的不一样了,所以遵循Java通用的开发规范“变量先声明后使用”是一个良好的编码风格。

注意 再次重申变量要先声明后使用,这不是一句废话。

[改善Java代码]静态变量一定要先声明后赋值的更多相关文章

  1. JAVA代码静态检测之PMD

    今天再次想启动Java代码静态检测工具的利用问题,主要再次尝试用了PMD,发现不少代码编码规范问题和好的代码建议,并学到不少自己之前没有注意到的Java方便的基础知识,感觉很不错,把相关明白的好的规则 ...

  2. java非静态变量初始化

    java费静态变量的初始化分为两种情况,一种是局部变量,一种是类的域. 对于类的域,java在类初始化时,会为变量赋一个初始值.对于基本数据类型,java会将初始值设置为二进制0,具体为将boolea ...

  3. 常量和静态变量会先载入内存后在进行执行php代码

    static $test=1;//在php执行前就已经写入内存$test++;var_dump($test);static $test=10;//在php执行前就已经写入内存var_dump($tes ...

  4. Java中静态变量的声明位置

    Java中静态变量只能是成员变量,局部方法中的局部变量除final外不能有任何其他修饰符,例如: public class Test { static String x = "1" ...

  5. 谈谈java中静态变量与静态方法在有继承关系的两个类中调用

    谈谈java中静态变量与静态方法在有继承关系的两个类中调用 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量和静态方法在有继承关系的两个类中的问题测试 ...

  6. Java 中静态变量和实例变量区别

    Java 中静态变量和实例变量区别 静态变量属于类,该类不生产对象,通过类名就可以调用静态变量. 实例变量属于该类的对象,必须产生该类对象,才能调用实例变量. 在程序运行时的区别: 实例变量属于某个对 ...

  7. GraalVM最佳实践,使用Java开发CLI、Desktop(JavaFX)、Web(SpringBoot)项目,并使用native-image技术把Java代码静态编译为独立可执行文件(本机映像)

    原创文章,转载请注明出处! 源码地址: Gitee Gtihub 介绍 GraalVM最佳实践,使用Java开发CLI.Desktop(JavaFX).Web(SpringBoot)项目,并使用nat ...

  8. java中静态变量,静态代码块,静态方法,实例变量,匿名代码块等的加载顺序

    转自:http://blog.csdn.net/mrzhoug/article/details/51581994 一.在Java中,使用”{}”括起来的代码称为代码块,代码块可以分为以下四种: 1.普 ...

  9. Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序

    在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...

随机推荐

  1. homework-08 C++课程课后思考与练习

    经过上次晚交作业导致没分以后 我再也不敢晚交作业了 今天就把这次作业先写了 homework Part 1 1. 理解C++变量的作用域和生命周期 a) 用少于10行代码演示你对局部变量的生命周期的理 ...

  2. homework-01 最大子串和

    题目描述 对于一个给定的数列,求该数列最大的子串和(连续) 问题分析 处理发生区间上的问题时,经常会用一个非常简单经典的思路——部分和(也有叫前缀和).部分和的思想在很多复杂的区间上的算法中都有应用, ...

  3. Spring EL Operators example

    Spring EL supports most of the standard mathematical, logical or relational operators. For example, ...

  4. UVaLive 7363 A Rational Sequence (二叉树)

    题意:给定一个二叉树,并对每一个进行编号和规定,现在给你一个值,问你是第几个. 析:这个题,我想了好久才想出来,这个真是数据结构练的太差了,不够扎实,这个题,应该从下向上推,如果分子大于分母,那么这个 ...

  5. MVC3 Razor模板引擎

    http://blog.csdn.net/tiz198183/article/details/8659362 一.Views文件夹 -> Shared文件夹下的 _Layout.cshtml 母 ...

  6. request,response,session

    1.request.getParameter("key")接受的是来自客户登陆端的数据,接受的是post或get方式传送的value. 2.请求的默认字符集是ISO-8859-1, ...

  7. PHP linux spl_autoload_register区分大小写

    一个PHP脚本用到spl_autoload_register,在WINDOWS下运行正常,但在LINUX就include不了,后来发现WINDOWS大小写不敏感,而在LINUX下区分大小写,WINDO ...

  8. oracle备份恢复之rman恢复到异机

    注意事项: 1 此处实验环境为同平台,同字节序,同版本,源机器和目标机器相同的目录结构. 2 目标机器只需要安装oracle数据库软件即可. 3 第一次利用备份恢复测试环境,之后从源机器拷贝备份到目标 ...

  9. contiki Makefile.include 四个关注点<contiki学习之二>

    Contiki Makefile.include 笔记 约定:  makefile 包括Makefile.Makefile.xxx,并不单指Makefile 不对makefile的语法进行分析,仅仅关 ...

  10. javascript 笔记(待续)

    1.基础对象  var o=new Object();  o.xxx=1; o.xx=2;    var 01={xxx=1,xx=2} 2.==与===   "5"==5 Tru ...