头疼的java面试题之传值,传址

roasperger 2010-02-11 12:56:01
据本人之拙见,java传值都是传数据的副本,修改其值不会影响原来的值,传地址会影响原来的值,头疼之代码如下:

public class Test {

public void change(int a) {
a = a + 1;
}
public void change2(int[] a, int[] b) {
a = b;
}

public void iter(int[] a) {
for(int i : a) {
System.out.print(i + " ");
}
}
public static void main(String[] aaaaaa) {
int num = 1;
int a[] = {1,1,1};
int b[] = {2,2,2};
Test t = new Test();
t.change(num);
t.change2(a,b);
System.out.print(num); /// num = 1
t.iter(a); // 为什么还是 “1 1 1”??? 难道数组不是引用类型的吗?不是传地址的?????

}
}

最后弱弱的问下各位高手,定义一个final类型的数组,为什么在程序中,其中的每个元素的值都能被改变?常量也能被改变吗?
...全文
913 47 打赏 收藏 举报
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
RomanticRabbit 2012-01-31
  • 打赏
  • 举报
回复
给你一个明白的解释
ganyiboy 2010-07-18
  • 打赏
  • 举报
回复
public class Test {
public static void change(int[] a, int[] b) {
a = b;
for(int i:a) {
System.out.println(i);
}
}
public static void main(String[] args) {
int a[] = {1, 1, 1};
int b[] = {3, 3, 3};
change(a, b);
for(int i: a) {
System.out.println(i);
}
}

}
我把你的代码改成这样,输出结果是:333111。可见是传值,不是传地址嘛。编译原理有个Display构造表还特别讲到这个呢。
坚持奋斗中1 2010-02-22
  • 打赏
  • 举报
回复
change 和change2方法没有返回值,main函数中定义的num=1和int a[] = { 1, 1, 1 };值都没有改变。修改如下:
public class Test {

public int change(int a) {
return a + 1;
}

public int[] change2(int[] a, int[] b) {
return b;
}

public void iter(int[] a) {
for (int i : a) {
System.out.print(i + " ");
}
}

public static void main(String[] aaaaaa) {
int num = 1;
int a[] = { 1, 1, 1 };
int b[] = { 2, 2, 2 };
Test t = new Test();
num=t.change(num);
a=t.change2(a, b);
System.out.println(num); /// num = 1
t.iter(a); // 为什么还是 “1 1 1”??? 难道数组不是引用类型的吗?不是传地址的?????

}
}
xiaozhu86 2010-02-22
  • 打赏
  • 举报
回复
数组是传的引用,正因为传的引用,所以打印出的a的值才没有变化,因为执行change2与主函数中的a跟本没关系啊,主函数的a一直指向{1,1,1}
xiaozhu86 2010-02-22
  • 打赏
  • 举报
回复
数组能直接赋值那样赋值?
xiaozhu86 2010-02-22
  • 打赏
  • 举报
回复
public void change2(int[] a, int[] b) {
for(int i=0;i<a.length;i++){
a[i]=b[i];
}
}
就是222
wlt0727 2010-02-22
  • 打赏
  • 举报
回复
public class Test {

public void change(int a) {
a = a + 1;
}
public Int[] change2(int[] a, int[] b) {
a = b;
return a;
}

public void iter(int[] a) {
for(int i : a) {
System.out.print(i + " ");
}
}
public static void main(String[] aaaaaa) {
int num = 1;
int a[] = {1,1,1};
int b[] = {2,2,2};
Test t = new Test();
t.change(num);
a[]=t.change2(a,b);
System.out.print(num); /// num = 1
t.iter(a);

}
}

这样就是22222了
jafapple 2010-02-22
  • 打赏
  • 举报
回复
引用楼主 roasperger 的回复:
据本人之拙见,java传值都是传数据的副本,修改其值不会影响原来的值,传地址会影响原来的值,头疼之代码如下:

public class Test {

  public void change(int a) {
      a = a + 1;
  }
  public void change2(int[] a, int[] b) {
      a = b;
  }

  public void iter(int[] a) {
      for(int i : a) {
          System.out.print(i + " ");
      }
  }
  public static void main(String[] aaaaaa) {
          int num = 1;
          int a[] = {1,1,1};
          int b[] = {2,2,2};
          Test t = new Test();
          t.change(num);
          t.change2(a,b);
          System.out.print(num);  /// num = 1
          t.iter(a);  //  为什么还是 “1 1 1”???  难道数组不是引用类型的吗?不是传地址的?????

  }
}

最后弱弱的问下各位高手,定义一个final类型的数组,为什么在程序中,其中的每个元素的值都能被改变?常量也能被改变吗?


没错,传的是地址,只不过原对象的地址拷贝。。。

如果你在里面修改数据或对象里的值,那么就会成功
Dazzlingwinter 2010-02-22
  • 打赏
  • 举报
回复
捡重点说:这里有四个int类型的一维数组的引用
main_a, main_b, change2_a, change2_b;
程序运行时,main_a, main_b被初始化
main_a 指向堆内存中的一片区域,存储内容为{1, 1, 1};
main_b 指向堆内存中的另外一片区域,存储内容为{2, 2, 2};
在调用change2(int[] a, int[] b)时
change2_a指向main_a指向的{1, 1, 1}, change2_b指向main_b指向的{2, 2, 2};
a = b;语句操作的结果是change2_a指向了change2_b指向的main_b指向的{2, 2, 2};
如果此时调用new Test().iter(a),将打印出{2, 2 ,2}的内容,前提是LZ的iter(int[] a)方法要做修改<<<System.out.print(a[i] + " ">>>
change2(int[] a, int[]b)方法运行结束,change2_a, change2_b局部变量被释放
而main_a所指向内容并没有发生改变,依然是{1, 1, 1};
另外LZ所写iter方法中并不是打印数组内容,打印的是数组index,System.out.print(a[i] + " ");
完毕
liuyiwu 2010-02-22
  • 打赏
  • 举报
回复
个人感觉:

public void change2(int[] a, int[] b)里面的参数数组a、b和main里的a、b数组是两个不同存储空间。以下把参数a、b数组成为参_a、参_b,把main里的数组a、b称为main_a、main_b。

main里调用t.change2(a,b)时:
参_a、参_b作为局部变量被创建。把main_a、main_b所持有的两个数组的引用(指针)传给参_a、参_b。这之后,main_a和参_a指向同一数组,main_b和参_b指向同一数组。

在change2里a = b;
把参_b赋给参_a。此时,参_a、参_b、main_b指向同一数组。

当离开change2函数时,参_a、参_b作为局部变量都被销毁。

在整个过程当中,main_a、main_b始终指向程序开始时给它们初始化的数组,因此不会发生任何改变。
xuexi100 2010-02-21
  • 打赏
  • 举报
回复
引用 14 楼 darxin 的回复:
基本数据类型的值传递理论是没有问题的。
Java codepublicclass Test {publicvoid change(int a) {
a= a+1;
}publicstaticvoid main(String[] args) {int num=1;
Test t=new Test();
t.change(num);
System.out.print(num);// num = 1 }
}

记住!引用类型的参数传递也是<span style="color:#FF0000">值</span>传递。
问题在于引用类型变量的值是什么?是对象的内存地址。
Java codepublicclass Test {publicvoid change2(int[] a,int[] b) {// 此时的局部变量a与主函数中的变量a是两个变量// 两个变量的值相同(指向同一个对象的地址) a= b;// 此时只改变了局部变量a的值,主函数变量a的值没有改变。 }publicstaticvoid main(String[] args) {int a[]= {1,1,1};int b[]= {2,2,2};
Test t=new Test();
t.change2(a, b);
t.iter(a);// 为什么还是 “1 1 1”??? 因为引用类型也是值传递! }publicvoid iter(int[] a) {for(int i : a) {
System.out.print(i+"");
}
}
}

我们可以在函数内部修改对象的内容,而不是变量的值。
Java codepublicclass Test {publicvoid change3(int[] a) {// 此时的局部变量a与主函数中的变量a是两个变量// 两个变量的值相同(指向同一个对象的地址) a[0]=2;// 此时改变的是对象的内容。// 局部变量a的值没有改变,仍然与主函数变量a的值相同。 }publicstaticvoid main(String[] args) {int a[]= {1,1,1};
Test t=new Test();
t.change2(a);
t.iter(a);// 结果为“2 1 1” }publicvoid iter(int[] a) {for(int i : a) {
System.out.print(i+"");
}
}
}

关键字final限制的是变量的值,而不是对象的内容。
Java codepublicclass Test {publicstaticvoid main(String[] args) {finalint a[]= {1,1,1};
a= {2,2,2};// 该语句在编译时报错,因为此时变量a的值不能改变。 a[0]=2;// 可以执行,因为改变的是对象的内容,与变量的值无关。 }
}

总之,这类让人头疼的问题本质在于变量的值与对象的内容 两者之间的区别。
看看Java中的数据比较(再谈==与equals的区别)一文,希望对楼主有所帮助。
acRush7 2010-02-17
  • 打赏
  • 举报
回复
这个好像解释比较清晰点。

引用 13 楼 potahai 的回复:
这个只是作用域起的作用啊,干吗整大惊小怪内。

NUM 和A[]  都不是类得成员变量。 方法里执行就是执行一次并不会给NUM A[] 进行赋值 你在你那个方法里输出就是你想要得 如果方法以外的话就是main里定义得初始状态
musiclee 2010-02-17
  • 打赏
  • 举报
回复
呵呵 类似c中的 **传值Fun(**a,**b){*a=*b}
wmdtksmld 2010-02-15
  • 打赏
  • 举报
回复
新年快乐 呵呵

为什么要限制字数
yaoliyuan321 2010-02-15
  • 打赏
  • 举报
回复
是常量还是引用 只要看定义对象时有没有new关键字,final数组用到了new表示在内存中实际为它分配了空间,int型数组每用到new,相当于还是常量
J_CodeLiving 2010-02-15
  • 打赏
  • 举报
回复
引用 30 楼 j_codeliving 的回复:
呵呵,初看代码,我也被小晕了下......

关键是你的2个change方法都没有返回值啊.


在补充一下:

从oo出发,这个Test类,设计的这2个change方法一点意义和用处都没有,当然除了让我犯了下晕.....
鄙视这种所谓的"题目"......

J_CodeLiving 2010-02-15
  • 打赏
  • 举报
回复
呵呵,初看代码,我也被小晕了下......

关键是你的2个change方法都没有返回值啊.

wfeng007 2010-02-14
  • 打赏
  • 举报
回复
1.java中只有值传递 没有引用传递
2.传地址本质也是值传递
3.虽然java中一直踢到reference,但是其实java中的变量(除了原始类型)都是指针,只不过美化过了,不能直接改变地址。

4。所以你可以考虑你把指针传过去当然能改变其中内容。
5。final 参数主要是指该参数的值不能被修改。如果你穿过的是地址,只是这个参数中的这个地址不能被修改。但是这个地址指向的内容是可以修改的。

kaka302 2010-02-12
  • 打赏
  • 举报
回复
就是一个变量作用域的问题,

LZ你把你2个函数的参数a,b修改成 x,y再看看就明白了
BadPattern 2010-02-12
  • 打赏
  • 举报
回复
假设你的change2方法改变成了 public void change2(int[] a1, int[] b1) {

执行了t.change2(a, b);以后,a和b把自己的引用赋给了形参a1和b1,这样a和a1指向同一个地址,b和b1指向了同一个地址。

在chang2方法内部,你把b1的指向赋给了a1,这样,指向信息又变成了:a指向原来的地址,b和b1和a1指向了同一个地址,a和b的指向并没有改变。

所以最后你打印a数据的值,当然没有任何变化。
加载更多回复(26)

62,620

社区成员

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

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