日期:2014-05-20  浏览次数:20672 次

一道java基础题目,有关static与final
这是我第一次发帖,求各位大牛帮忙!
Java code

import java.util.*;

class Parent {
    //public static int i = 3;                        //去掉注释,执行static代码段的代码
    //public static final int i = 3;                  //去掉注释,不执行static代码段的代码
    public final int i = new Random().nextInt(100);   //执行static代码段的代码
    
    static {
        System.out.println("parent static block");
    }
}

public class TestClassLoader {
    public static void main(String[] args) {
        System.out.println(p.i);
    }
}



请各位大牛解释一下上面三种情况的输出。我的问题是,为什么第三种输出会是那样,和第二种有什么区别

------解决方案--------------------
Java code
import java.util.*;

class Parent {
    //public static int i = 3;      //1、静态变量,类加载的时候赋值,可以类运行时类的方法中修改                 
    //public static final int i = 3;  //2、静态常量,类加载的时候赋值,不可以可以类运行时类的方法中修改                     
      public final int i = new Random().nextInt(100);  //3、类的实例变量 ,即只有使用new 一个类变量时,他才存在 ,不能修改,初始化时赋值     
    static {
        System.out.println("parent static block");
    }
}

public class TestClassLoader {
    public static void main(String[] args) {
        Parent p = new Parent() ;
        System.out.println(p.i);
//1 、
     parent static block
    3
//2、  
     parent static block
    3
//3、
    parent static block
   随机数

    }
}

------解决方案--------------------
搞不懂你不明白的是啥,楼上的解释足够了吧
------解决方案--------------------
首先我觉得你要表达的意思是下面这段代码
import java.util.*;

class Parent {
// public static int i = 3; //去掉注释,执行static代码段的代码
// public static final int i = 3; //去掉注释,不执行static代码段的代码
public static final int i = new Random().nextInt(100); //执行static代码段的代码

static {
System.out.println("parent static block");
}
}

public class TestClassLoader 
{
public static void main(String[] args) 
{
System.out.println(Parent.i);
}
}

接着我来分析分析你的问题
第一种:当程序执行到System.out.println(Parent.i);他发现没有parent这段字节码,系统的类加载器就会自动加载这个字节码,因为public static int i = 3; 他在编译的时候会把这段程序放在静态代码快中,所以程序先输出System.out.println("parent static block");然后输出3
第二种:当程序执行到System.out.println(Parent.i);他发现没有parent这段字节码,系统的类加载器就会自动加载这个字节码,因为public static final int i = 3; 系统在编译的时候已经能确定i的值了,因为你要去输出i的值,所以他就不会去执行静态代码快,
第二种的定义相当于C语言中的#define,定义一个宏
第三种:当程序执行到System.out.println(Parent.i);他发现没有parent这段字节码,系统的类加载器就会自动加载这个字节码,因为public static final int i = new Random().nextInt(100); 因为编译器在编译的时候不能确定它的值,只有在运行的时候才能知道它的值,所以必须的运行他的静态代码块


------解决方案--------------------
探讨

首先我觉得你要表达的意思是下面这段代码
import java.util.*;

class Parent {
// public static int i = 3; //去掉注释,执行static代码段的代码
// public static final int i = 3; //去掉注释,不……

------解决方案--------------------
探讨

首先我觉得你要表达的意思是下面这段代码
import java.util.*;

class Parent {
// public static int i = 3; //去掉注释,执行static代码段的代码
// public static final int i = 3; //去掉注释,不……

------解决方案--------------------
其区别在于final,被final修饰的变量在编译阶段就将此变量的值存储到了NoInitialization类的常量池中。而static只是说明这个变量的调用方式以及初始化时间。
------解决方案--------------------
这个跟类的加载机制有关,声明为final的变量在编译阶段就将此变量的值存储到了常量池中,所以调用Parent.i就不用加载Parent这个类