据本人之拙见,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类型的数组,为什么在程序中,其中的每个元素的值都能被改变?常量也能被改变吗?
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类型的数组,为什么在程序中,其中的每个元素的值都能被改变?常量也能被改变吗?
例如final int[] array = new int[10]; // array只是一个4字节的内存地址值, 并没有占用10个int的内存空间.
注意, 把array传给一个函数的时候, 传递的是array存储的内存地址值的副本, 并不是他所指向的10个int的那一段内存的副本.所以当你给array赋值时, 因为他是final的, 编译会报错, 但是给array[1]等赋值的时候, 是给他指向的内存赋值, 并不是array本身, 所以没问题.
关于 Java 中对象的复制。
System.out.println("交换前的a-HASH"+a.hashCode());
System.out.println("交换前的b-HASH"+b.hashCode());
a = b;
System.out.println("交换后的a-HASH"+a.hashCode());
System.out.println("交换后的b-HASH"+b.hashCode());
System.out.println(a);
} 今天又有点晕,胡说八道在所难免。
public void change(int a) {
a = a + 1;
} public static void main(String[] args) {
int num = 1;
Test t = new Test();
t.change(num);
System.out.print(num); // num = 1
}
}
记住!引用类型的参数传递也是值传递。
问题在于引用类型变量的值是什么?是对象的内存地址。public class Test {
public void change2(int[] a, int[] b) {
// 此时的局部变量a与主函数中的变量a是两个变量
// 两个变量的值相同(指向同一个对象的地址)
a = b;
// 此时只改变了局部变量a的值,主函数变量a的值没有改变。
} public static void 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”??? 因为引用类型也是值传递!
}
public void iter(int[] a) {
for(int i : a) {
System.out.print(i + " ");
}
}
}
我们可以在函数内部修改对象的内容,而不是变量的值。public class Test {
public void change3(int[] a) {
// 此时的局部变量a与主函数中的变量a是两个变量
// 两个变量的值相同(指向同一个对象的地址)
a[0] = 2;
// 此时改变的是对象的内容。
// 局部变量a的值没有改变,仍然与主函数变量a的值相同。
} public static void main(String[] args) {
int a[] = {1,1,1};
Test t = new Test();
t.change2(a);
t.iter(a); // 结果为“2 1 1”
}
public void iter(int[] a) {
for(int i : a) {
System.out.print(i + " ");
}
}
}
关键字final限制的是变量的值,而不是对象的内容。public class Test {
public static void main(String[] args) {
final int a[] = {1,1,1};
a = {2,2,2}; // 该语句在编译时报错,因为此时变量a的值不能改变。
a[0] = 2; // 可以执行,因为改变的是对象的内容,与变量的值无关。
}
}
总之,这类让人头疼的问题本质在于 变量的值与对象的内容 两者之间的区别。
看看Java中的数据比较(再谈==与equals的区别)一文,希望对楼主有所帮助。
s.append("b");
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("a");
new Test1().change(s);
System.out.println(s.toString()); // 结果是 ab
}
}这个应该是标准的传地址吧....如果参数有作用域的话,那么这个s是不应该改变的啊.....
s.append("b"); // 此处改变的是对象的内容,不是变量的值。
}
public Test1(int a) {
this.n = a;
}
public void add(int nn) {
this.n = nn;
}
public static void main(String[] args) {
int n = 444;
System.out.println(new Test1(22).n); // 结果成员变量n的值改变了
new Test1(22).add(n);//结果成员变量n的值不能改变,这又是为什么呢?
}
public int n = 2; public Test(int a) {
this.n = a;
} public void add(int nn) {
this.n = nn;
} public static void main(String[] args) {
int n = 444;
Test t1 = new Test(22);
System.out.println(t1.n); // 22 Test t2 = new Test(22);
t2.add(n);
System.out.println(t2.n); // 444
}
}
问题提得莫名其妙!
a = a + 1;
}
public void change2(int[] a, int[] b) {
a[0]=100;
} public void iter(int[] a) {
for(int i : a) {
System.out.println(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.println(num); /// num = 1
t.iter(a); // 为什么还是 “1 1 1”??? 难道数组不是引用类型的吗?不是传地址的????? }
} 输出的是:100 1 1
数组是OBJECT,其实ab两个OBJECT还是那两个OBJECT,但是如果这个两对像的中的元素发生了变化..就会有变化. a = b;
只是作为函数内的参数..与你在主函数中初始化的对像是无关的...
class Test1 { public int n = 2; public Test1(int a) {
this.n = a;
}
public void add(int nn) {
this.n = nn;
}
public static void main(String[] args) {
int n = 444;
System.out.println(new Test1(22).n); // 结果成员变量n的值改变了
new Test1(22).add(n);//结果成员变量n的值不能改变,这又是为什么呢?
}可是刚才怎么都不能改变成员变量的值了,不知道是不是jdk的问题,重启了下电脑,再试发现可行了..呵呵
谢谢各位了!!!
a = a + 1;
} public void change2(int[] a, int[] b) {
a[0] = 2;
a = b;
a[0] = 1;
} 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.println(num); // / num = 1
t.iter(a); // 为什么还是 “1 1 1”??? 难道数组不是引用类型的吗?不是传地址的?????
System.out.println();
t.iter(b);
}}
java传值是对的,不过应该这样子理解:简单类型直接复制一个新的值,而对象则是复制了传递对象的地址传递过去。
其实所有的对象(完整地说是对象实例引用变量)可以理解为一个简单变量,只不过这个变量中存的是实例内容地址,而简单类型直接就是存的相应的数据。
针对这里,main中的a和change2方法的a是具有相同的对象实例引用地址的两个值变量,所以,这个时候a[0] = 2;改变的就是main中a引用的实例,两个内容都会被改变,因为两个变量存的地址相同;但是当在方法中a=b时,方法中a变量的值,就是引用地址变为了b得,但是main中的a变量的值所引用实例地址并没有改变。
可以这样子简单的理解,对象(变量)可以理解为指针,指针只是存储了实例的地址,是一个简单对象,所以,当你把它等于另外一个对象,只是指针变化了。而java中传值,所以,不会影响原来的指针指向的地址。
2.传地址本质也是值传递
3.虽然java中一直踢到reference,但是其实java中的变量(除了原始类型)都是指针,只不过美化过了,不能直接改变地址。4。所以你可以考虑你把指针传过去当然能改变其中内容。
5。final 参数主要是指该参数的值不能被修改。如果你穿过的是地址,只是这个参数中的这个地址不能被修改。但是这个地址指向的内容是可以修改的。
在补充一下: 从oo出发,这个Test类,设计的这2个change方法一点意义和用处都没有,当然除了让我犯了下晕.....
鄙视这种所谓的"题目"......
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”??? 难道数组不是引用类型的吗?不是传地址的????? }
}
参_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始终指向程序开始时给它们初始化的数组,因此不会发生任何改变。
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] + " ");
完毕
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了
for(int i=0;i<a.length;i++){
a[i]=b[i];
}
}
就是222
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构造表还特别讲到这个呢。