鱼C论坛

 找回密码
 立即注册
查看: 4547|回复: 12

类的加载问题?

[复制链接]
发表于 2018-4-16 21:17:58 | 显示全部楼层 |阅读模式
4鱼币
论坛的大神们,有个问题困扰着我,具体看代码:
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合并,是否是因为这个? Snipaste_2018-04-16_21-14-54.png

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-4-17 06:57:00 From FishC Mobile | 显示全部楼层
跟据变量的生命周期,int a,是全局变量,所以在这个全局范围内在什么地方都可以用,你多注意一下局部变量和全局变量有什么特点,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-4-17 16:29:35 | 显示全部楼层
本帖最后由 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。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-4-19 10:15:57 | 显示全部楼层
ABC23 发表于 2018-4-17 16:29
首先代码没问题。a=9。
===============
分析:Java是以class为基本单位组织代码的。首先JVM加载Instance ...

也就是说,尽管int a是在后面声明的,但是,在加载时它是先被执行的?
能详细说一下为什么会有这种“提前”呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-4-19 10:59:49 | 显示全部楼层
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.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-4-19 13:55:24 | 显示全部楼层
ABC23 发表于 2018-4-19 10:59
先声明,后使用。这是变量的基本准则。
在Java中,不像C99那样严格。你可以在比较『随意』的地方进行声 ...

我觉得你说的有点问题,请参看链接https://segmentfault.com/q/1010000012954285
按里面的解释,int a是在之前就已经被加载过了,我查了一些资料,非静态的代码块,成员变量等在类加载的时候会被init方法合并,静态的会被clinit合并,但是具体怎么合并,产生什么效果,中文资料全都语焉不详,英文的看不懂。。。你看我问题里的图和链接里的图,确实在字节码里,int a跑到前面去了,但是不是init起的作用就不得而知了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-4-19 14:08:39 | 显示全部楼层
ABC23 发表于 2018-4-19 10:59
先声明,后使用。这是变量的基本准则。
在Java中,不像C99那样严格。你可以在比较『随意』的地方进行声 ...

我大概知道了,int a这个声明早在类加载时就已经声明了,给了默认值0,clinit和init与这个并没有关系,合并的是赋值语句。这个问题因该是类在加载时做的某种“优化”。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-4-19 19:37:36 | 显示全部楼层
ylyl 发表于 2018-4-19 14:08
我大概知道了,int a这个声明早在类加载时就已经声明了,给了默认值0,clinit和init与这个并没有关系,合 ...

有什么问题?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-4-19 21:25:45 | 显示全部楼层

具体就是,int a到底是怎么跑到前面去的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-11-26 21:06:06 | 显示全部楼层
不错的问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-11-27 16:23:06 | 显示全部楼层
a = 6啥玩意? 不报错才怪
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-3-2 19:57:28 | 显示全部楼层
那么简单的问题.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-3-2 19:58:23 | 显示全部楼层
类加载,代码块就执行,a没声明
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 12:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表