Java - 在匿名方法中更改参数对象

Java - Change a parameter object inside anonymous method

我今天遇到了这个,我不太明白发生了什么。

目的是创建一个可以更改参数对象的匿名方法。我虽然想出了一种聪明的方法来传递值并在不同对象之间修改它们,而无需明确了解另一个对象,但有些地方出了问题。 以下代码概述了一般问题:

void foo() {
    String a = "foo";

    MethodMap.addMethod("1", new Method() {
        @Override
        public void execute(Object ... args) {
             args[0] = "bar";
        }
    } );
    MethodMap.invoke("1", a);
    System.out.println(a);
}

class MethodMap {
    private static Map<String, Invocation> map = new HashMap<>();

    public static boolean addMethod(String key, Invocation method) {
        map.put(key, method);
    }

    public static void invoke(String key, Object ... args){
        map.get(key).execute(args);
    }
}

public interface Invocation {
    public void execute(Object ... args);
}

我的本意是这段代码应该输出 bar,但它输出 foo。我不太清楚为什么。 Java-objects 不是通过引用传递的吗?那样的话,难道我不能修改它们吗?

有人可以解释一下我错过了什么吗?

我对该领域术语的了解实际上可能限制了我在线搜索此内容的能力,因为我不知道要用什么词 Google。

谢谢 // 西蒙

Java 始终按值传递。除了在声明它的方法中重新分配它之外,您根本无法更改局部变量指向的内容。与其他一些语言不同,您不能传递 a "by reference" 并让另一个方法更新它指向的内容。

通过指定 arg[0] = "bar",您已成功将值 "bar" 分配给参数数组的第一个元素。但这对 a.

没有影响

参见:

  • Is Java "pass-by-reference" or "pass-by-value"?

args[] 是匿名 MethodMap 实例中的局部变量,它指的是隐式创建的临时数组,用于保存 .invoke(...) 调用的额外参数。

分配 args[0] 时,您所做的只是更新临时数组。


void foo() {
    // a is a local variable in your foo() method that refers to an
    // immutable String object with the value, "foo".
    String a = "foo";

    MethodMap.addMethod("1", new Method() {
        @Override

        // args is a local variable in the execute() method, that refers
        // to a temporary Array object. 
        public void execute(Object ... args) {

             // This assignment changes the zeroth element of the temporary
             // array to point to a String object with the value, "bar".
             args[0] = "bar";
        }
    } );

    // The compiler turns your MethodMap.invoke() call into this:
    //       Array<Object> tmp = new Array<Object>[1];
    //       tmp[0] = a;   // tmp[0] now refers to the same immutable String as a.
    //       MethodMap.invoke("1", tmp);
    // The tmp array is ignored after the invoke call returns.
    MethodMap.invoke("1", a);

    System.out.println(a);
}