最近在总结一些自己以前学JAVA的东西,这次搞的是初始化的问题。先不说问题,大家先看
下面2个类:package initial;public class AmazingCls {
//final static double a = Math.random();
final static int a = 18;
static{
System.out.println("-----static---------");
}
public AmazingCls(){
System.out.println("------对象被创建---");
}
public static void main(String[] args){
// int b = AmazingCls.a;
System.out.println("------main()--------");
}
}
package initial;public class AmazingTest { public static void main(String[] args) { //new AmazingCls();
//int b = AmazingCls.a;
System.out.println("------main()--------"); }}运行第一个例子(注释那句去掉与否不影响输出效果),输出:
-----static---------
------main()--------运行第二个例子,输出:
------main()--------
加上int b = AmazingCls.a;这句,输出还是:
------main()--------
再加上new AmazingCls();这句,输出:
-----static---------
------对象被创建---
------main()--------好了看到这里我的问题是什么呢?相信高手已经知道了,这就是主动调用与被动调用的问题
到底那些情况是主动调用?
哪些是被动调用呢?
我发此贴的目的就是与大家探讨下这个问题我现在的总结是:
用new生成对象就是对此类的主动调用;直接运行有main()的类也是对此类的主动调用;
类的成员变量在执行期间才能得到值的,访问此成员也可是对此类的主动调用。比如:final static double a = Math.random();
那么被动调用都是哪些情况呢?大家一起帮忙总结下,不吝赐教~~~~~~感谢~~~~~~
下面2个类:package initial;public class AmazingCls {
//final static double a = Math.random();
final static int a = 18;
static{
System.out.println("-----static---------");
}
public AmazingCls(){
System.out.println("------对象被创建---");
}
public static void main(String[] args){
// int b = AmazingCls.a;
System.out.println("------main()--------");
}
}
package initial;public class AmazingTest { public static void main(String[] args) { //new AmazingCls();
//int b = AmazingCls.a;
System.out.println("------main()--------"); }}运行第一个例子(注释那句去掉与否不影响输出效果),输出:
-----static---------
------main()--------运行第二个例子,输出:
------main()--------
加上int b = AmazingCls.a;这句,输出还是:
------main()--------
再加上new AmazingCls();这句,输出:
-----static---------
------对象被创建---
------main()--------好了看到这里我的问题是什么呢?相信高手已经知道了,这就是主动调用与被动调用的问题
到底那些情况是主动调用?
哪些是被动调用呢?
我发此贴的目的就是与大家探讨下这个问题我现在的总结是:
用new生成对象就是对此类的主动调用;直接运行有main()的类也是对此类的主动调用;
类的成员变量在执行期间才能得到值的,访问此成员也可是对此类的主动调用。比如:final static double a = Math.random();
那么被动调用都是哪些情况呢?大家一起帮忙总结下,不吝赐教~~~~~~感谢~~~~~~
解决方案 »
- 多线程连接MySQL数据库,报 Communications link failure
- 重新问一个,struts怎么制作复杂的表格?
- java里能不能申请固定的内存空间
- 请问正则表达式可以实现如下的功能么?
- String args[]?String[] args?
- 求助:有一个程序只有界面,没有功能,是个简单的统计程序,哪位热心高手能帮忙实现,很急,高手可能半个小时不到就可以完成,我会报答你
- 时间的'上午''下午'是什么格式的??
- 请教各位高手,关于JDBC 的下载
- 请问这段初始化代码为什么出错??谢谢
- 如何用DataSource建立数据库连接!
- 大家猜猜有几行输出语句
- java如何在图片上增加热点 可链接
难道是对常量的访问并不需要static初始化?估计是的。学习下去
------main()-------- 我说的是这个
说的很模糊啊类肯定要初始化的,jvm调用前,在类装载的时候必须初始化,初始化时static{}要执行的。
当类型进行以下操作时被认为是类型主动调用,类型必须初始化。
当创建一个类的实例时(无论是new还是反射,克隆,反序列化等等)。
当调用某个类的静态方法时。
当调用某个类的静态字段或者给其赋值时(此处必须是类自身定义的字段,不能为父类字段,而且不能为常量,常量不被认为是类的成员字段)
当调用api的某些反射方法对类型进行访问时
当初始化这个类型的子类时
当这个类是程序入口时,即程序启动是通过这个类中的main方法时。
这个,解决了我的部分疑问
那当
final static double a = Math.random();
这样定义时,结果又是不一样的,怎么解释呢?
a不是常量?
或者运行期确定值的也是主动调用?
static final int a = (int)Math.random(); // 运行时常量,在运行的时候才能确定知道这个之后,问题就迎刃而解了,
因为你的final static int a = 18;
是编译时常量,所以int b = AmazingCls.a;
会被编译成int b = 3,这样就不会涉及到类AmazingCls的装载,也就不会调用这个类的static 块了。
对于final static double a = Math.random();
是运行时常量,必须装载类之后才能够得到值。下面我给出一个例子:public class Client
{
static final int a = 3;
static {
System.out.println("static block");
}
public Client() {
System.out.println("Client initialize!");
}
public static void main(String[] args) {
System.out.println("Client main");
}
}class Other {
public static void main(String[] args) {
int b = Client.a;
System.out.println("other main");
}
}类Other编译后的class文件内容为:
class com.ibm.datatools.we.test.Other {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
Other();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 51]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: com.ibm.datatools.we.test.Other
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 2, Locals: 2
public static void main(java.lang.String[] args);
0 iconst_3
1 istore_1 [b]
2 getstatic java.lang.System.out : java.io.PrintStream [16]
5 ldc <String "other main"> [22]
7 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
10 return
Line numbers:
[pc: 0, line: 53]
[pc: 2, line: 55]
[pc: 10, line: 56]
Local variable table:
[pc: 0, pc: 11] local: args index: 0 type: java.lang.String[]
[pc: 2, pc: 11] local: b index: 1 type: int
}
看到没有,那个地方被替换成3了。
看了以上的回帖,问题集中在final上。
下面是我的理解:
如果是:
final static double a = 3;//Math.random();
则编译的时候将a作为常量。
当你调用double b = AmazingCls.a;
可以直接得到值是3.如果你去掉了final,则这个值就要在运行时候再计算。
则要加载AmazingCls类,所以才会打印出static块的内容。如果是:
final static double a = Math.random();
不管是否有final,a不会是编译时候可以得到的值。
所以必须要去运行时计算,
则要加载AmazingCls类,所以才会打印出static块的内容。
否者要加载类!
类一加载-static 调用
final static double a = Math.random();
这个是运行期常量,只有在程序运行时才能出结果
final static double a = 3;
这个是编译期常量
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.