这是我的代码,请在阅读问题之前先查看一下
package ict201jansem2012;
public class Qn3b {
public static void main(String[] args) {
int a = 1;
int b[] = {4,5};
String s = "Good luck!";
method1(b[1]);
System.out.println("(1) b[0] = "+b[0]+"; b[1] = "+b[1]);
method2(b);
System.out.println("(2) b[0] = "+b[0]+"; b[1] = "+b[1]);
method3(a);
System.out.println("(3) a = " + a );
method4(s);
System.out.println("(4) s = " + s );
}
public static void method1(int b) {
b = 7;
}
public static void method2(int[] b) {
b[0] = 3;
}
public static void method3(int a) {
a = 3;
}
public static void method4(String s) {
s = "UniSIM";
}
}
输出: (1)b [0] = 4; b [1] = 5
(2)b [0] = 3; b [1] = 5
(3)a = 1
(4)s =祝你好运!
所以我的问题是, 这对于我来说是有趣的学习程序员。 int b数组0索引值已更改,但不是其他变量,如String s和int a。在我运行这个程序之前,我粗略地认为变量将在调用方法时改变它们的值,这是因为正在调用该方法并且传递主要方法,例如a,s和b数组,然后它们正在修改。
那么简而言之,为什么b数组0索引被改变而其他变量没有改变?
答案 0 :(得分:3)
因为你说你是一名初学程序员,我会做一些文章来解释(或尝试解释)完全正在发生的事情。
这是因为您要将参数传递给 method1 - method4 方法
这些参数本身就是对其他对象的引用。
使用赋值运算符时,使用等号,可以覆盖当前范围中值的引用 - 其中变量可以“看到”。
在您的代码中:
对于 method1 ,您正在创建新引用,该变量只能在该范围内看到。也就是说,当你去 b =<< expr>>您要在 method1 的范围内为变量b分配值,而不是 main 范围中的b。您的 method3 和 method4 方法也是如此,您正在为该范围内的 中的相应变量分配新值,因为您正在创建新的参考而不是改变原始对象。
但是, method2 的代码行为有所不同,这是因为您正在改变该代码中的对象。您正在直接更改对象 - 而不是在该范围内创建新引用。
考虑以下代码
int[] array = new int[] {1, 2};
public void test()
{
method1(array);
System.out.println(array[0] + ", " + array[1]);
method2(array);
System.out.println(array[0] + ", " + array[1]);
}
// because we are working with objects, the identifier, can be different to the arrays identifier
// in this case, I've chosen to use 'a' instead of 'array' to show this
public void method1(int[] a)
{
// this mutates the array object
a[0] = 2;
}
public void method2(int[] array)
{
// this overwrites the method2.array but not the global array
array = new int[] { 1, 2, 3 };
}
我们创建一个新数组,在全局范围内使用identifer'array'。 (在Java中,这将是类自己的范围)
在 method1 中,我们接受一个参数,它是作为全局数组对象传递的同一个对象,所以当我们改变它时,两个对象都会改变。所以,第一个print语句将是
“2,2”
其中array [0]已被更改
N.B。因为我们处理对象,变量的“名称”无关紧要 - 它仍然是对同一对象的引用
但是,在 method2 中,我们接受一个参数,就像在 method1 中一样,但是这次我们使用赋值运算符将该变量赋值给范围中的新值它目前在 - 所以全局数组没有改变,所以我们仍然打印出来
“2,2”
对于初学者程序员,我会亲自编写一些测试程序,让您完全了解变量和范围的工作原理。
但要知道,每次创建新的块代码时,都会创建一个新的范围,只能在该范围内看到该范围的局部变量低于它。
例如:
public void test()
{
int a = 5;
method1(a);
System.out.println(a); // prints 5
}
public void method1(int a)
{
// a is only viewable in the method1 scope
// and any scopes below it, that is, any scopes created within method1
// and since we use an assignment operator, we assign method1.a a value, not global 'a' a value
a = 123;
if (true)
{
// this is a new scope, variables created in this block cannot be seen outside it
// but can see variables from above it
System.out.println(a); // prints 123
}
}
在这里,我们在if语句中的 method1 中创建了一个新的范围,它可以在上面看到它。但是,因为 method1 和 test 的作用域都是独立的,所以当我们使用赋值运算符时,我们将 a 的值赋给本地范围。所以 a 在 test 和 method1
中是不同的我希望你现在明白了。 我不是很善于传达事物,但是如果它甚至帮助了解范围我做得很好,加上,这很有趣。
答案 1 :(得分:2)
Java是按值传递的,但是大多数值(所有不是原语的东西,在本例中为int []和String)都是引用,这意味着它们就像传递引用一样。
答案 2 :(得分:1)
arrays
是特殊类型的对象,内存将在HEAP上分配。将数组作为参数传递给方法时,它将作为引用值传递(引用的副本)。
这意味着初始b
,这个新引用指向同一个对象。除非新引用指向另一个对象,否则此引用的更改将反映在同一对象上。这就是为什么你看到原始数组反映了价值的原因。
答案 3 :(得分:0)
所有值都传递给内部方法,但内部方法没有返回任何内容。但是,method2修改了传递给它的数组的内部值,以便在返回时修改内部值。
请注意,method2是未分配给变量(参数)本身的唯一一个,而是分配给传入引用的对象的元素英寸
修改对象的引用(指针)和修改对象本身之间存在着重要的区别。