关于这个问题原先偶然在群里见他们讨论,但最后无果了结。后来在群中网友的帮助下找到了关于这个问题的一篇文章,这里己记不清出处,所以仅是作为笔记记在这里。
public class StaticTest { static{//静态块在静态变量之前声明 a=100; } public static int a=10; public static void main(String[] args) { System.out.println(StaticTest.a);//这里打印出的是10,说明public static int a=10;在static块之后 执行 } }
一个类在你用之前有“装载,链接,初始化”这么几个阶段,链接又有“验证,准备,解析”这三个阶段。
装载就是把2进制的class文件加载到JVM。
链接就是分配内存,将符号引用解析为直接引用还有给变量赋默认值。(静态变量[类变量]就是在这个阶段创建的)
初始化就是执行初始化语句和初始化块。初始化顺序为(见The Java Language Specification§12.4.2 ):
<fieldset>
9. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they
were a single block, except that final class variables and fields of interfaces
whose values are compile-time constants are initialized first (§8.3.2.1, §9.3.1,
§13.4.9).
</fieldset>
好,再看你的代码:
public static int a
a这个变量是在准备阶段创建的(链接的第二个阶段),创建玩并给了默认值0,int变量的默认值为0.然后到类的初始化阶段按照文本中出现的先后顺序进行 初始化。先执行static块中的,初始化为100,然后再执行你声明时的显示初始化 a=10,最后a的值为10.所以在main中打印的结果就位10了。
再看你的第二个疑问,为什么会有“非法先前引用”的问题。
先看The Java Language Specification§8.3.2.3 的描述:
<fieldSet>
The declaration of a member needs to appear textually before it is used only if
the member is an instance (respectively static) field of a class or interface C and
all of the following conditions hold:
• The usage occurs in an instance (respectively static) variable initializer of C
or in an instance (respectively static) initializer of C.
• The usage is not on the left hand side of an assignment.
• The usage is via a simple name.
• C is the innermost class or interface enclosing the usage.
</fieldset>
就是说 如果以下四种情况全部满足,那么类C的成员要在用之前声明:(大概翻译下,不是很准确)
1·在(实例/静态)变量初始化器中或者(实例/静态)初始化器中使用
2·使用时不在赋值语句的左边
3·通过简单名词使用
4·C是一个最内部的类但是在外部的类中使用
public class StaticTest { static{ System.out.println(a);//static块中使用a符合上述情况,要在使用前声明,所以出现了一个error。 // 如果改为System.out.println(StaticTest.a)就不会报错了。(不符合第3点,没使用简单名称a,而用了StaticTest.a) } public static int a=10; public static void main(String[] args) { System.out.println(StaticTest.a); } }
public class StaticTest { static{ a=20;//这个a在赋值语句的左边,不符合第2点。所以是可以的。 } public static int a=10; public static void main(String[] args) { System.out.println(StaticTest.a); } }
相关推荐
java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用命令和插件java Maven中常用...
java字符串的处理,java中常用字符串方法总结,java中常用字符串方法总结,
JAVA中常用的数据结构,适用参加工作初期的Java开发者。
在日企得得朋友可以看看,........
Java中常用类API.ppt
Java中常用字符串方法总结
Java中常用的数据库连接方式有以下几种: JDBC(Java Database Connectivity): JDBC是Java提供的标准数据库连接API,可以与各种关系型数据库进行交互。JDBC提供了一组接口和类,用于连接数据库、执行SQL语句并...
Java中常量分类.pdf 学习资料 复习资料 教学资源
在java中常出现的错误
浅谈Java中常用数据结构的实现类Collection和Map共7页.pdf.zip
Java中常用的数据库连接池[定义].pdf
java代码-使用java解决学生管理系统的问题的源代码 ——学习参考资料:仅用于个人学习使用!
列举了使用ssh进行web开发时常遇到的一些问题
对java常用命令java及javac做了深入介绍,以及这些命令在带包情况下的不同使用方式。
C语言考试中常出现的问题
给你精讲面试中常出现的261个Java语言问题
一共84个jar包,java开发中常使用的,减少您网上搜索的时间
工具类 基础的类型 对象 数据的工具,进行判断或者进行操作
java面试中常设计到的问题。希望对于一些刚找工作的java程序员有一些帮助!
在java 操作中常碰见的问题!适合初学者,步骤详细,解答具体。谢谢!