`
fhqibjg
  • 浏览: 53643 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

java中常用不常知的问题

阅读更多

     关于这个问题原先偶然在群里见他们讨论,但最后无果了结。后来在群中网友的帮助下找到了关于这个问题的一篇文章,这里己记不清出处,所以仅是作为笔记记在这里。

 

 

Java code
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>  
好,再看你的代码:

 

Java code
    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是一个最内部的类但是在外部的类中使用

Java code
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);
    }  
}

 

Java code
public class StaticTest {  
    static{
        a=20;//这个a在赋值语句的左边,不符合第2点。所以是可以的。
    }
    public static int a=10;
    public static void main(String[] args) {
        System.out.println(StaticTest.a);
    }  
}  

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics