A ref = new A()的执行顺序问题

jn0115 2014-05-08 09:45:49
如题,A ref = new A() 这个语句的执行顺序是?
1, 先在堆上申请一块内存,然后执行构造函数,最后让ref指向该对象。

还是

2. 先在堆上申请一块内存,然后让ref指向该对象,最后执行构造函数。

还是

3. 1跟2都有可能。
...全文
1317 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuebichongkafei 2014-05-13
  • 打赏
  • 举报
回复
引用 12 楼 liyang0410 的回复:
画内存图么。
表上数字顺序就更清楚了, 程序从上到下从左到右,所以,先在栈中创建引用变量再在堆中创建对象,然后将堆中的内存地址赋值给栈中的引用变量,所以,是先申请内存,无论是栈还是堆.
jn0115 2014-05-11
  • 打赏
  • 举报
回复
引用 19 楼 lxbccsu 的回复:
[quote=引用 16 楼 jn0115 的回复:] 你这指令不能证明是1的情况啊,怪我没把问题描述清楚。其实这个问题是放到多线程环境下考虑的,虽然指令的执行顺序证明是1的情况,但是就算先可见性的问题,可能导致构造函数中的某些域没写被写回共享内存去,导致其他线程看到局部对象。
不要 生搬硬套 什么可见性,回写共享内存,多线程环境 啥的。 你确保你弄明白了上面说的到底是个什么概念! 问你几个问题: A ref = new A() 创建对象会线程共享? 创建这个对象有多线程问题吗?Java栈会发生线程并发问题吗? 至于 重排序问题, 在采用JDK 6 编译时,用 Oracle 的编译器(Sun) 编译时 是没有发现什么编译优化、指令重排序;至于运行期是否进行指令重排序,我是不知道,但可以肯定的是:指令执行的最终效果应当与其在顺序执行下的效果一致的; 最后,你想描述什么,可以继续了。 [/quote] 好吧。你很强
lxbccsu 2014-05-11
  • 打赏
  • 举报
回复
引用 16 楼 jn0115 的回复:
你这指令不能证明是1的情况啊,怪我没把问题描述清楚。其实这个问题是放到多线程环境下考虑的,虽然指令的执行顺序证明是1的情况,但是就算先可见性的问题,可能导致构造函数中的某些域没写被写回共享内存去,导致其他线程看到局部对象。
不要 生搬硬套 什么可见性,回写共享内存,多线程环境 啥的。 你确保你弄明白了上面说的到底是个什么概念! 问你几个问题: A ref = new A() 创建对象会线程共享? 创建这个对象有多线程问题吗?Java栈会发生线程并发问题吗? 至于 重排序问题, 在采用JDK 6 编译时,用 Oracle 的编译器(Sun) 编译时 是没有发现什么编译优化、指令重排序;至于运行期是否进行指令重排序,我是不知道,但可以肯定的是:指令执行的最终效果应当与其在顺序执行下的效果一致的; 最后,你想描述什么,可以继续了。
alan19931103 2014-05-11
  • 打赏
  • 举报
回复
我弱弱的问一下,知道这个以后可以干什么?
jn0115 2014-05-11
  • 打赏
  • 举报
回复
引用 1 楼 lxbccsu 的回复:
[quote=引用 楼主 jn0115 的回复:] 如题,A ref = new A() 这个语句的执行顺序是? 1, 先在堆上申请一块内存,然后执行构造函数,最后让ref指向该对象。 还是 2. 先在堆上申请一块内存,然后让ref指向该对象,最后执行构造函数。 还是 3. 1跟2都有可能。
自己测试下: 如:

public class Test {

	public static void main(String[] args) {
		Test t = new Test();
	}

}
字节码是(JDK1.6): Code: Stack=2, Locals=2, Args_size=1 0: new #1; //class lxb/csdn/Test 3: dup 4: invokespecial #16; //Method "<init>":()V 7: astore_1 8: return 明显是 先在堆上申请一块内存,然后执行构造函数,最后让ref指向该对象;[/quote] 你这指令不能证明是1的情况啊,怪我没把问题描述清楚。其实这个问题是放到多线程环境下考虑的,虽然指令的执行顺序证明是1的情况,但是就算先可见性的问题,可能导致构造函数中的某些域没写被写回共享内存去,导致其他线程看到局部对象。
teemai 2014-05-10
  • 打赏
  • 举报
回复
javap 看字节码能说明问题
北落师门_Orz 2014-05-10
  • 打赏
  • 举报
回复
当然是先申请一块堆内存来保存 ref这个对象 , 然后执行方法,方法中的对象保存在栈内存中,最后让ref指向该对象
vnvlyp 2014-05-09
  • 打赏
  • 举报
回复
不看具体编译结果,想想应该也是先构造再赋值吧。 不然你还没构造好,变量指向一块垃圾数据岂不是比null更危险,Java不会让你做这种事情的吧。
漏扫老司机 2014-05-09
  • 打赏
  • 举报
回复
mark 一下! 觉得1,2都有可能!
ForestDB 2014-05-09
  • 打赏
  • 举报
回复
你来写编译器,想怎么执行顺序就什么执行顺序。
sunbo624 2014-05-09
  • 打赏
  • 举报
回复
刚学Java的时候就知道 构造函数不是像C++一样用来创建对象的 而是初始化对象的 所以 new A()是先malloc 然后根据你调用的构造函数初始化 这条语句返回一个地址 A ref指向那个地址
sg_knight 2014-05-09
  • 打赏
  • 举报
回复
1、在堆上申请一块内存 2、执行构造函数 3、让ref指向该对象;
wula0010 2014-05-09
  • 打赏
  • 举报
回复
为什么要讨论这个呢?你想改变顺序?还是想在中间做什么?1楼编译的后的结果,只能说在你使用的编译器的情况下是这样,如果换个编译器呢,结果不一定吧?所以完全没有必要纠结这个,这是java,不是c/c++...............
cjb7625 2014-05-09
  • 打赏
  • 举报
回复
1和2都有可能,参看指令重排序。
grapepaul 2014-05-09
  • 打赏
  • 举报
回复
是1和2都有可能的。 但Unittest不是很容易测试出来。 建议搜索相关主题 java单例模式双重检查成例/java编译器原理 希望对你有帮助
咖啡不放糖 2014-05-09
  • 打赏
  • 举报
回复
画内存图么。
lliiqiang 2014-05-09
  • 打赏
  • 举报
回复
肯定是1,只有构造函数被执行完成以后才能返回赋值给ref
sleeplacker 2014-05-08
  • 打赏
  • 举报
回复
当然是执行了构造函数以后才有对象,有了对象以后引用才能有所指
haorengoodman 2014-05-08
  • 打赏
  • 举报
回复
A ref = new A() 这个语句如果是在方法中出现,ref 会在栈的本地变量表中,然后在堆中生成一分实例,并将实例引用赋值给ref
lxbccsu 2014-05-08
  • 打赏
  • 举报
回复
引用 楼主 jn0115 的回复:
如题,A ref = new A() 这个语句的执行顺序是? 1, 先在堆上申请一块内存,然后执行构造函数,最后让ref指向该对象。 还是 2. 先在堆上申请一块内存,然后让ref指向该对象,最后执行构造函数。 还是 3. 1跟2都有可能。
自己测试下: 如:

public class Test {

	public static void main(String[] args) {
		Test t = new Test();
	}

}
字节码是(JDK1.6): Code: Stack=2, Locals=2, Args_size=1 0: new #1; //class lxb/csdn/Test 3: dup 4: invokespecial #16; //Method "<init>":()V 7: astore_1 8: return 明显是 先在堆上申请一块内存,然后执行构造函数,最后让ref指向该对象;

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧