类的加载问题?
论坛的大神们,有个问题困扰着我,具体看代码:public class Instance{{
a=6;
}
int a=9;
public static void main(String[] args) {
System.out.println(new Instance().a);
}
}
类初始化时代码块和成员变量的优先级是相同的,谁在前先执行谁。那么a=6时,a这个变量还没声明啊,怎么会不报错?我javap查看后发现int a跑到了第一行,查资料有说非静态的这些在类加载时会被linit合并,静态的被clinit合并,是否是因为这个? 跟据变量的生命周期,int a,是全局变量,所以在这个全局范围内在什么地方都可以用,你多注意一下局部变量和全局变量有什么特点,
本帖最后由 ABC23 于 2018-4-17 16:35 编辑
首先代码没问题。a=9。
===============
分析:Java是以class为基本单位组织代码的。首先JVM加载Instance类,同时载入声明的成员变量a=0(基本类型初始化为0)
接着因为代码块的优先级较高(在前面),现将a赋值为6;接着代码顺序执行,a=6覆盖原来的a(两个a实际上指向同一块内存)。
综上,a=9。
===============
关于局部代码块,只要注意『在局部代码块内部声明的变量只存活于代码块内部』就可以了。
...
a = 6;
{
int a = 9;
}
...
这会抛出一个Error。 ABC23 发表于 2018-4-17 16:29
首先代码没问题。a=9。
===============
分析:Java是以class为基本单位组织代码的。首先JVM加载Instance ...
也就是说,尽管int a是在后面声明的,但是,在加载时它是先被执行的?
能详细说一下为什么会有这种“提前”呢? ylyl 发表于 2018-4-19 10:15
也就是说,尽管int a是在后面声明的,但是,在加载时它是先被执行的?
能详细说一下为什么会有这种“提 ...
先声明,后使用。这是变量的基本准则。
在Java中,不像C99那样严格。你可以在比较『随意』的地方进行声明,甚至同时声明和使用。
代码是自上而下执行的,所以先执行前面的在执行后面的。想要执行a=6但是没有声明,于是就去找。在后面找到int a = 9;这里拆成两部分看:1)int a,2)a=9,即先声明,后使用。这里我们只要前半句。于是a声明生效,a被初始化为0(因为是基本类型),接着立即把6赋值给a,现在a=6.最后代码接着向下执行,a=9. ABC23 发表于 2018-4-19 10:59
先声明,后使用。这是变量的基本准则。
在Java中,不像C99那样严格。你可以在比较『随意』的地方进行声 ...
我觉得你说的有点问题,请参看链接https://segmentfault.com/q/1010000012954285
按里面的解释,int a是在之前就已经被加载过了,我查了一些资料,非静态的代码块,成员变量等在类加载的时候会被init方法合并,静态的会被clinit合并,但是具体怎么合并,产生什么效果,中文资料全都语焉不详,英文的看不懂。。。你看我问题里的图和链接里的图,确实在字节码里,int a跑到前面去了,但是不是init起的作用就不得而知了 ABC23 发表于 2018-4-19 10:59
先声明,后使用。这是变量的基本准则。
在Java中,不像C99那样严格。你可以在比较『随意』的地方进行声 ...
我大概知道了,int a这个声明早在类加载时就已经声明了,给了默认值0,clinit和init与这个并没有关系,合并的是赋值语句。这个问题因该是类在加载时做的某种“优化”。 ylyl 发表于 2018-4-19 14:08
我大概知道了,int a这个声明早在类加载时就已经声明了,给了默认值0,clinit和init与这个并没有关系,合 ...
有什么问题? ABC23 发表于 2018-4-19 19:37
有什么问题?
具体就是,int a到底是怎么跑到前面去的 不错的问题 a = 6啥玩意? 不报错才怪 那么简单的问题. 类加载,代码块就执行,a没声明
页:
[1]