两个数组 a,b ,System.out.println(a[(a=b)[3]]);结果不明白

walkman154 2007-01-15 12:45:03
public class A
{
public static void main(String args[])
{
int[] a={11,12,13,14};
int[] b={0,1,2,3};
System.out.println(a[(a=b)[3]]);
System.out.println(a[2]);
}
}
结果为:
14
2

有点不明白为什么?
...全文
794 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
mymyhope 2007-01-21
  • 打赏
  • 举报
回复
public class A
{
public static void main(String args[])
{
int[] a={11,12,13,14};
int[] b={0,1,2,3};
System.out.println(a[((a=b))[a[3]]]);
System.out.println(a[2]);
}
}
为什么运行结果也是
14
2
nirvana_li 2007-01-19
  • 打赏
  • 举报
回复
source code;
public static void main(String args[])
{
/* 3*/ int ai[] = {
/* 3*/ 11, 12, 13, 14
};
/* 4*/ int ai1[] = {
/* 4*/ 0, 1, 2, 3
};
/* 5*/ System.out.println(ai[(ai = ai1)[3]]);
}
bytecode:
public static void main(String args[])
{
/* 3*/ // 0 0:iconst_4
/* 3*/ // 1 1:newarray int[]
/* 3*/ // 2 3:dup
/* 3*/ // 3 4:iconst_0
/* 3*/ // 4 5:bipush 11
/* 3*/ // 5 7:iastore
/* 3*/ // 6 8:dup
/* 3*/ // 7 9:iconst_1
/* 3*/ // 8 10:bipush 12
/* 3*/ // 9 12:iastore
/* 3*/ // 10 13:dup
/* 3*/ // 11 14:iconst_2
/* 3*/ // 12 15:bipush 13
/* 3*/ // 13 17:iastore
/* 3*/ // 14 18:dup
/* 3*/ // 15 19:iconst_3
/* 3*/ // 16 20:bipush 14
/* 3*/ // 17 22:iastore
/* 3*/ // 18 23:astore_1
/* 4*/ // 19 24:iconst_4
/* 4*/ // 20 25:newarray int[]
/* 4*/ // 21 27:dup
/* 4*/ // 22 28:iconst_0
/* 4*/ // 23 29:iconst_0
/* 4*/ // 24 30:iastore
/* 4*/ // 25 31:dup
/* 4*/ // 26 32:iconst_1
/* 4*/ // 27 33:iconst_1
/* 4*/ // 28 34:iastore
/* 4*/ // 29 35:dup
/* 4*/ // 30 36:iconst_2
/* 4*/ // 31 37:iconst_2
/* 4*/ // 32 38:iastore
/* 4*/ // 33 39:dup
/* 4*/ // 34 40:iconst_3
/* 4*/ // 35 41:iconst_3
/* 4*/ // 36 42:iastore
/* 4*/ // 37 43:astore_2
/* 5*/ // 38 44:getstatic #2 <Field PrintStream System.out>
/* 5*/ // 39 47:aload_1
/* 5*/ // 40 48:aload_2
/* 5*/ // 41 49:dup
/* 5*/ // 42 50:astore_1
/* 5*/ // 43 51:iconst_3
/* 5*/ // 44 52:iaload // Load int from array Stack!
/* 5*/ // 45 53:iaload // Load int from array Stack!
/* 5*/ // 46 54:invokevirtual #3 <Method void PrintStream.println(int)>
/* 6*/ // 47 57:return
}
我认为由于java虚拟机是基于栈结构的,所以在编译的时候,对于ai[(ai = ai1)[3]]这样的表达式会进行优化,所以ai是仍然存在于堆栈中的原来的值。

而再一次System.out.println(a[2])的bytecode:
47 57:getstatic #2 <Field PrintStream System.out>
48 60:aload_1
49 61:iconst_2
50 62:iaload // Load int from array Stack!
51 63:invokevirtual #3 <Method void PrintStream.println(int)>
这一次又重新装入新的ai.
Moon 2007-01-16
  • 打赏
  • 举报
回复
很无聊的问题
但是有助于深入理解Java的机制
这肯定是考试的题,故意考人的
程序员工作中不会这么写的~
egghitler 2007-01-16
  • 打赏
  • 举报
回复
这问题相当简单啊,看一遍就明白了啊!!
健之 2007-01-16
  • 打赏
  • 举报
回复
其实这个问题的关键在于表达式的优先级和运算秩序的问题,只要能够确定运算和引用秩序的先后,结果就不难分析了。不过麻烦是像楼主这样的写法在语言标准中没有明确规定其优先级和运算秩序,在写编译和解释程序的时候,各公司的具体程序员可能只能根据自己的理解和方便来确定其运算和引用的先后秩序,所以严格的说,不同的编译器对这类问题的运算结果不一定一致。所以个人觉得,每个写得好的编译器可能会支持这样的写法,但使用者应该避免这样的写法,到不是因为难理解,而是因为结果可能是不定的。
software_jianghai 2007-01-16
  • 打赏
  • 举报
回复
应该先是a[]指向的是原来的a数组,然后在a=b,这个时候a指向b了
java_road 2007-01-16
  • 打赏
  • 举报
回复
a=b是b 把对应的值全部附给a相对应的值.所以1楼的理解有点问题.
java_road 2007-01-16
  • 打赏
  • 举报
回复
class A
{
public static void main(String args[])
{
int[] a={11,12,13,14};
int[] b={0,1,2,3};
System.out.println(a[(a=b)[3]]);
System.out.println(a[2]);
System.out.println(a[3]);
}
}
加上一行就能看清楚了。
结果是
14
2
3
说明是先打印再传值.
sky3168095 2007-01-16
  • 打赏
  • 举报
回复
关键是数组也是引用类型
Atai-Lu 2007-01-16
  • 打赏
  • 举报
回复
whyxx(最近有点闲) ( ) 信誉:105 Blog 2007-1-15 17:01:42 得分: 0

其实个人觉得研究这样的东西没意义,我手下要有人敢把程序写成这样,非骂死他不可.呵呵
============================
赞同~程序写出来了,还要进行维护。如果程序里这样摸棱两可的东西太多,维护起来就很困难了。
yifuzhiming 2007-01-16
  • 打赏
  • 举报
回复
有什么意义??没用过
sg552 2007-01-16
  • 打赏
  • 举报
回复
同意上面某楼。

如果哪个SB程序员敢这么写,肯定被叼死没商量的。
「已注销」 2007-01-15
  • 打赏
  • 举报
回复
javap反汇编一下class就很容易理解了
daniel_zwn 2007-01-15
  • 打赏
  • 举报
回复
先读了a,再改变a,再读第二次.
For_suzhen 2007-01-15
  • 打赏
  • 举报
回复
这样写的不是老师就是学生,不会是职员,老师会出这样的题,学生会研究这样的题,如果职员写了,等死行了。呵呵
lower0661 2007-01-15
  • 打赏
  • 举报
回复
不知理解的对不对:
表达式因为由左至右扫描,所以先将a[(a=b)[3]]中最外层的a连同其值(数组a的首地址)加入内存,暂记为a1.然后执行a=b,这样的话(a=b)[3]是3没有问题,再得a1[3]就是14。此语句结束,表达式包括赋值生效,a与b指向同一地址,第二句a[2]便是2。

但是也有一个疑问:同一语句读到两个a,如果这样理解的话两个a的值是分别存储的了,不知道是不是这样~
walkman154 2007-01-15
  • 打赏
  • 举报
回复
还是有些不解
千里冰封820 2007-01-15
  • 打赏
  • 举报
回复
因为解析算术表达式从左开始,如果能从内部改变原来a的指向的话,那就会有不可预料的事情发生
syoumei 2007-01-15
  • 打赏
  • 举报
回复
呵呵 有点出乎意料

a首先被引用所以没有指向b空间
-----------------------------
同意

a[...]已经指向了原来a数组的地址,(a=b)就好像修改环境配置文件,但只有下次启动有用

- -!

walkman154 2007-01-15
  • 打赏
  • 举报
回复

执行(a[(a=b)[3]])的过程,首先程序执行到第一个a但由于[]中又有一个执行语句且语句中又有a指针的调用,所以编译器会先给a设了个临时指针pa放到内存中等待[]中的结果返回后在计算。
然后a=b 使a的指针指向了b,所以
(a=b)[3] 其实是等于b[3]值为3,而a[(a=b)[3]]其实是a[3]=14,注意这个a其实调用的是一开始在内存中保存的哪个pa,它还指向的是a原来的位置所以a[3]为14而不是3。到了下行,a的已经指向了b,a[2]其实就是b[2]所以为2
加载更多回复(9)

62,614

社区成员

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

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