【问题标题】:Only array is being modified只有数组被修改
【发布时间】:2012-11-01 03:03:18
【问题描述】:

这是我的代码,请在阅读问题之前查看它

 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的索引改变了,而其他变量没有改变?

【问题讨论】:

    标签: java variable-assignment


    【解决方案1】:

    因为你说你是初学者程序员,所以我会写一些文章来解释(或尝试解释)确切发生了什么。

    这是因为您将参数传递给您的 method1 - method4 方法

    这些参数本身就是对其他对象的引用。

    当您使用赋值运算符(一个等号)时,您会覆盖当前作用域中值的引用——其中可以“看到”变量。

    在您的代码中:

    method1 的情况下,您正在创建一个新引用,该变量只能在该范围内看到。也就是说,当你然后去 b = > 你是在 method1 的范围内为变量 b 分配值,而不是在 main 范围。您的 method3method4 方法也是如此,您正在为该范围内的各个变量分配一个新值,因为您正在创建新的引用而不是改变原来的对象。

    但是,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 };
    }
    

    我们创建一个新数组,在全局范围内具有标识符“数组”。 (在 Java 中,这将是类自己的范围)

    method1中,我们接受一个参数,它是作为全局数组对象传递的同一个对象,所以当我们改变它时,两个对象都会改变。所以,第一个打印语句将是

    “2, 2”

    array[0] 被改变的地方

    注意因为我们处理的是对象,所以变量的“名称”并不重要——它仍然是对同一个对象的引用

    然而,在 method2 中,我们接受一个参数,就像在 method1 中一样,但这次我们使用赋值运算符将该变量分配给范围内的新值它当前在 - 所以全局 array 没有改变,所以我们仍然打印出来

    “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中创建了一个新的作用域,可以看到它上面的a。但是,由于method1test的作用域都是独立的,所以我们在使用赋值运算符时,会将a的值赋给本地范围。所以 atestmethod1

    中都是不同的

    我希望你现在能更好地理解。 我不太擅长传达东西,但如果它对理解范围有所帮助,我做得很好,而且很有趣。

    【讨论】:

      【解决方案2】:

      Java 是按值传递的,但大多数值(所有非原始值,在本例中为 int[] 和 String)都是引用,这意味着它们的行为类似于按引用传递。

      这是一篇不错的文章:http://javadude.com/articles/passbyvalue.htm

      【讨论】:

        【解决方案3】:

        arrays 是特殊类型的对象,内存将在 HEAP 上分配。当您将数组作为参数传递给方法时,它将作为引用值(引用的副本)传递。

        这意味着初始 b 并且这个新的引用指向同一个对象。除非新的引用指向另一个对象,否则对这个引用的更改将反映在同一个对象上。这就是为什么您会看到价值反映在原始数组上的原因。

        【讨论】:

          【解决方案4】:

          所有的值都传递给内部方法,但内部方法什么也没返回。但是,method2 修改了传递给它的数组的内部值,因此内部值在返回时出现了修改。

          请注意,method2 是唯一一个您没有分配给变量(参数)本身,而是分配给其引用被传递的对象的元素的方法在。

          修改对对象的引用(指针)和修改对象本身之间有一个关键的区别。

          【讨论】:

            猜你喜欢
            • 2015-07-10
            • 1970-01-01
            • 2011-03-15
            • 1970-01-01
            • 2012-12-21
            • 1970-01-01
            • 2019-10-17
            • 2016-04-19
            • 1970-01-01
            相关资源
            最近更新 更多