关于这个问题原先偶然在群里见他们讨论,但最后无果了结。后来在群中网友的帮助下找到了关于这个问题的一篇文章,这里己记不清出处,所以仅是作为笔记记在这里。
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中常用的数据结构进行详细的介绍。 Collection接口 Collection接口是JAVA中所有集合类的父接口,它提供了基本的集合操作方法,如add、remove、...
Java 中常用日语词汇 Java 是一种广泛应用于软件开发的编程语言,日本企业在开发 Java 项目时经常使用的一些日语词汇。本文档整理了一些常用的日语词汇,旨在帮助开发者更好地理解和使用 Java 相关技术。 计算机...
Java Web 开发中常遇到的问题 在 Java Web 开发中,开发者经常会遇到一些棘手的问题,影响项目的进度和质量。在这篇文章中,我们将列举一些常见的问题,并对其进行解释和解决。 1. java.lang....
Java中常用类API.ppt
java中常用类,String,Math等
在Java编程语言中,字符串是极其重要...以上就是Java中常用字符串方法的总结。理解并熟练运用这些方法,将极大地提升你在处理字符串时的效率和代码质量。在实际开发中,还需要结合具体需求灵活选择和组合使用这些方法。
在java中常出现的错误
Java 中常用字符串方法总结 Java 中的字符串是极其重要的数据类型之一,字符串的操作和处理在 Java 开发中占据着非常重要的地位。下面是 Java 中常用字符串方法的总结。 创建并初始化字符串 在 Java 中,可以使用...
本文将详细介绍这两个命令的使用方法,以及在处理带有包的Java程序时如何操作。 `javac`是Java语言的编译器,负责将源代码转换为字节码的`.class`文件。在命令行中,你可以使用以下格式来调用`javac`: ```bash ...
Java编程语言中的常量是不可变的值,它们在程序执行过程中始终保持不变。常量的使用有助于提高代码的可读性和可维护性。本篇将详细介绍Java中的五种常量类型:整型常量、浮点型常量、字符型常量、布尔型常量以及字符...
- 为了持久化数据,系统可能使用JDBC(Java Database Connectivity)接口连接数据库,如MySQL或SQLite,将学生信息存储到表中。这包括编写SQL语句(如INSERT, DELETE, UPDATE, SELECT)以及处理结果集。 4. **异常...
### Java中常用的数据库连接方式 #### JDBC (Java Database Connectivity) **定义与作用:** JDBC 是 Java 提供的一套标准数据库访问 API,它支持与各种关系型数据库进行交互。通过 JDBC,开发者可以使用统一的...
C语言考试中常出现的问题
在Java编程语言中,工具类(Utils)是包含各种实用方法的类,这些方法...理解并熟练使用这些工具类,对于提升Java编程能力至关重要。通过不断学习和实践,我们可以更好地利用这些工具类,写出更加高效、健壮的代码。
本文将详细介绍Java中常用的数据库连接池,包括它们的工作原理、特点以及主要配置。 1. 数据库连接池的原理 数据库连接池的基本思想是在系统启动时预先创建一定数量的数据库连接并存储在内存中。当应用程序需要访问...
给你精讲面试中常出现的261个Java语言问题
在Java编程语言中,数据结构是组织和存储数据的基本方式,它们为算法的高效执行提供了基础。本篇文章将深入探讨两个重要的数据结构实现类:Collection和Map,以及它们在Java中的应用。 首先,Collection是Java集合...
标题提到的"java开发中常使用的JAR包"集合提供了一站式的解决方案,免去了开发者在网上寻找和验证各种依赖的繁琐工作。这些JAR包涵盖了从基础功能到特定任务处理的各种组件,极大地丰富了Java的开发环境。 首先,...
Java 面试中常设计到的问题,以下是对标题和描述中所说的知识点的详细说明: Core Java * 线程:Java 中的线程是通过 Thread 类或 Runnable 接口来实现的。线程的生命周期包括新建、就绪、运行、等待、睡眠、死亡...