[改善Java代码]静态变量一定要先声明后赋值
建议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代码]静态变量一定要先声明后赋值的更多相关文章
- JAVA代码静态检测之PMD
今天再次想启动Java代码静态检测工具的利用问题,主要再次尝试用了PMD,发现不少代码编码规范问题和好的代码建议,并学到不少自己之前没有注意到的Java方便的基础知识,感觉很不错,把相关明白的好的规则 ...
- java非静态变量初始化
java费静态变量的初始化分为两种情况,一种是局部变量,一种是类的域. 对于类的域,java在类初始化时,会为变量赋一个初始值.对于基本数据类型,java会将初始值设置为二进制0,具体为将boolea ...
- 常量和静态变量会先载入内存后在进行执行php代码
static $test=1;//在php执行前就已经写入内存$test++;var_dump($test);static $test=10;//在php执行前就已经写入内存var_dump($tes ...
- Java中静态变量的声明位置
Java中静态变量只能是成员变量,局部方法中的局部变量除final外不能有任何其他修饰符,例如: public class Test { static String x = "1" ...
- 谈谈java中静态变量与静态方法在有继承关系的两个类中调用
谈谈java中静态变量与静态方法在有继承关系的两个类中调用 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量和静态方法在有继承关系的两个类中的问题测试 ...
- Java 中静态变量和实例变量区别
Java 中静态变量和实例变量区别 静态变量属于类,该类不生产对象,通过类名就可以调用静态变量. 实例变量属于该类的对象,必须产生该类对象,才能调用实例变量. 在程序运行时的区别: 实例变量属于某个对 ...
- GraalVM最佳实践,使用Java开发CLI、Desktop(JavaFX)、Web(SpringBoot)项目,并使用native-image技术把Java代码静态编译为独立可执行文件(本机映像)
原创文章,转载请注明出处! 源码地址: Gitee Gtihub 介绍 GraalVM最佳实践,使用Java开发CLI.Desktop(JavaFX).Web(SpringBoot)项目,并使用nat ...
- java中静态变量,静态代码块,静态方法,实例变量,匿名代码块等的加载顺序
转自:http://blog.csdn.net/mrzhoug/article/details/51581994 一.在Java中,使用”{}”括起来的代码称为代码块,代码块可以分为以下四种: 1.普 ...
- Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序
在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...
随机推荐
- Hibernate之基于外键映射的一对一(1-1)关联关系
1.对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素.为many-to-one元素增加unique="true"属性来表示为1 ...
- Hibernate初认识以及HelloWorld
一.Hibernate初认识 1. Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. 2.对 ...
- Shell统计报表表格生成
基本需求 分析完数据后,一般需要将数据以附件的形式发送处理,这个已经在<>中有介绍,如何 用Python实现附件的发送. 但不是所有人都关心附件的内容,一般邮件中需要有些概要的信息,如附件 ...
- Spring Auto scanning components
Normally you declare all the beans or components in XML bean configuration file, so that Spring cont ...
- C:移位运算符
1在向右移位时,空出的位是由0填充,还是由符号位的副本填充? 如果被移位的对象是无符号数,那么空出的位将被0填充.如果被位移的对象是有符号数,那么C语言实现既可以用0填充空出的位,也可以用符号位的副本 ...
- uva10474 简单排序查找 一次AC
题目很简单,加上读题20分钟一次AC.还是用到了快排qsort. #include<iostream> #include<cstdlib> using namespace st ...
- ural 1303 Minimal Coverage(贪心)
链接: http://acm.timus.ru/problem.aspx?space=1&num=1303 按照贪心的思想,每次找到覆盖要求区间左端点时,右端点最大的线段,然后把要求覆盖的区间 ...
- 【Todo】ipcs命令学习
可以先看这一篇 http://www.jb51.net/article/40805.htm
- C#中的强制类型转换与as转换的区别
C#中的强制类型转换 例如有ClassA与ClassB两个类创建两个类的对象进行转换 1 2 ClassA a = new ClassA(); ClassB b = new ClassB(); 如果 ...
- 有关static静态修饰符的学习心得
初学java,面对着这个static修饰符,愣是琢磨了两天时间,还在今天琢磨透了,现在将悟到的东西记录下来: 1.static修饰符表示静态修饰符,其所修饰的内容(变量.方法.代码块暂时学到这三种)统 ...