写出如下代码的运行结果并给出解释
- Java code
class Test { static { System.out.println("***"); } public static final String a = "sss"; public static String test() { return "###"; }}public class T { public static void main(String[] args) { System.out.println(Test.a); System.out.println(Test.test()); }}请给出你的理由。。。。。
###########################
老紫竹利用特权,修改一下这个题目
###########################
这个类编译后会生成2个对象
T.class
Test.class
我们把Test.class删除,单独运行T.class 会发生什么呢??
System.out.println(Test.a);
会执行吗?
System.out.println(Test.test());
会执行吗?
[解决办法]
[解决办法]
sss
***
###
[解决办法]
sss
***
###
final类型的特殊性。
[解决办法]
那个final 是关键,他会让编译器优化,并不会去真正使用Test类,而是直接在
System.out.println(Test.a);
优化成了
System.out.println("sss");
这就是结果
[解决办法]
java编译器发现class T中使用了class Test时,就会查找Test.class文件,如果没有找到这个文件,就会自动搜索Test.java然后进行编译。
在编译过程中由于final的特性,编译器首先会查找final所修饰的变量然后执行初始化语句,紧接着再根据一般初始化的顺序继续执行其他语句。
所以顺序是:sss *** ###
如果把a前面的final修饰符去掉顺序就不一样,因为初始化的顺序不一样了。
[解决办法]
学习一下
[解决办法]
[解决办法]
mark 学习了
[解决办法]
我修改了帖子,增加了问题。希望能认清楚
final 到底是什么!!!
[解决办法]
试过了,通不过
[解决办法]
support
[解决办法]
Java里一切东西都会出现在类里。很多时候这个特性会很烦琐。毕竟Java仍流有C的血液。
在C的使用习惯里,const是很有意义的,因此java保留了这一特性。也即final存在的初衷。
既然这个是表示常量的,javac理所当然的认为程序运行时JVM不会改变它,于是自作主张的将其改为“Constant”,也就是说跟类没有关系了。这个真真意义上的常量对用户和程序员是透明的,这样比起每次都要重类里加载数据而言,放在常量区的话会提高效率。所以有了上述结果。
[解决办法]
运行结果:
sss
***
###
分析:
1、由于a同时被修饰为static和final,它属于类的资源,就是类在被加载进内存的时候(也就是应用程序启动的时候)就要已经为此属性分配了内存,即在类的加载之前进行初始化的,可通过类名直接进行访问。所以在以上代码的:System.out.println(Test.a);会先打印出***;此时并没有进行Test类的加载;
2、当执行到System.out.println(Test.test());首先是进行Test类的加载,而static块 ,一般是一个类初始化时运行的代码,注意,是类的初始化,不是对象的初始化。 因此此时先会打印出***,紧接着才调用test()方法,打印出###。
不知道这样解释是否清楚。
[解决办法]
谢谢,各位大虾!我一直以为是static先加载的了
今天有学到了
[解决办法]
咳
第一反应是:
***
SSS
###
看了几位大侠的回答才醒悟...
[解决办法]
sss
***
###
[解决办法]
以下是 javap 结果
- BatchFile code
Compiled from "T.java"public class T extends java.lang.Object{public T(); Code: 0: aload_0 1: invokespecial #8; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #22; //String sss 5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream; 11: invokestatic #30; //Method test20080713/Test.test:()Ljava/lang/String; 14: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 17: return}Compiled from "T.java"class Test extends java.lang.Object{public static final java.lang.String a;static {}; Code: 0: getstatic #13; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #19; //String *** 5: invokevirtual #21; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: returnTest(); Code: 0: aload_0 1: invokespecial #30; //Method java/lang/Object."<init>":()V 4: returnpublic static java.lang.String test(); Code: 0: ldc #36; //String ### 2: areturn}
[解决办法]
又学了一招
[解决办法]
学习了
[解决办法]
原来是这样的,终于有点懂了
[解决办法]
一起学习了。
[解决办法]
都是final static惹得祸
[解决办法]
[解决办法]
对了,还有一个final参数,
final argument 相当于c/c++中的 const argument
[解决办法]
这个是经常考得一个题目
远行一遍就明白多了
[解决办法]
学习了,谢谢!
[解决办法]
晕,我还以为***先执行呢
[解决办法]
学习了
[解决办法]
受益匪浅
[解决办法]
学习!
[解决办法]
ding
ding
[解决办法]
[解决办法]
学习了。Java的类,让人造成误解,以为写到类里的代码,就都属于这个类。其实是个常量。
[解决办法]
[解决办法]
有点意思
[解决办法]
对final static String a的赋值放到static{}里,执行结果就是先输出sss了,因为final static类型的变量,必须先初始化值才可以。
[解决办法]
[解决办法]
顶
[解决办法]
高手如云
[解决办法]
楼主的例子是外部调用类的静态final常量, 并且该常量初始化语句是编译时的常量表达式。
只能说这种情况不符合"类首次主动被使用时"的初始化规则,因此不会导致类的初始化。运行以下代码的结果表明,外部调用类的编译时静态final常量,甚至都不会导致Test类被ClassLoader加载,也就更不会做类的初始化动作了。
class Test {
static {
System.out.println("***");
}
public static final String a = "sss";
public static String test() {
return "###";
}
}
public class T {
public static void main(String[] args) {
System.out.println(Test.a);
}
}
编译Test.java和T.java
在命令行执行:java -verbose T
以下为部分输出:
...........................................................................
[Loaded java.security.AllPermission from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.security.UnresolvedPermission from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.security.BasicPermissionCollection from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.lang.Long$1 from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.security.Principal from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.security.cert.Certificate from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded T]
sss
[Loaded java.lang.Shutdown from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\j2re1.4.2_09\lib\rt.jar]
[解决办法]
sss
***
###
因为static不需要初始化,可 以直接调用