Java-在匿名方法中更改参数对象
我今天遇到了这件事,我不能完全理解正在发生的事情 目的是创建一个可以更改参数对象的匿名方法。我想我想出了一个聪明的方法,可以在不同的对象之间传递值并修改它们,而不需要对另一个对象有明确的了解,但有些事情是错误的。 以下代码概述了一般问题:Java-在匿名方法中更改参数对象,java,anonymous,Java,Anonymous,我今天遇到了这件事,我不能完全理解正在发生的事情 目的是创建一个可以更改参数对象的匿名方法。我想我想出了一个聪明的方法,可以在不同的对象之间传递值并修改它们,而不需要对另一个对象有明确的了解,但有些事情是错误的。 以下代码概述了一般问题: void foo() { String a = "foo"; MethodMap.addMethod("1", new Method() { @Override public void execute(Obje
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);
}
void foo(){
字符串a=“foo”;
addMethod(“1”,新方法(){
@凌驾
公共void执行(对象…参数){
args[0]=“条形”;
}
} );
方法映射调用(“1”,a);
系统输出打印项次(a);
}
类方法图{
private static Map=new HashMap();
公共静态布尔addMethod(字符串键、调用方法){
map.put(键、方法);
}
公共静态void调用(字符串键、对象…参数){
map.get(key).execute(args);
}
}
公共接口调用{
公共作废执行(对象…参数);
}
我的意图是该代码应该输出bar,但它输出foo。我不太清楚为什么。Java对象不是通过引用传递的吗?在这种情况下,我不能修改它们吗
有人能解释一下我遗漏了什么吗
我在这个领域的术语知识实际上可能限制了我在网上搜索这个词的能力,因为我不知道谷歌应该用什么词
谢谢//SimonJava总是按值传递。除了在声明局部变量的方法中重新分配它之外,您无法更改局部变量指向的对象。与其他一些语言不同,您不能“通过引用”传递
a
,而让另一个方法更新它所指向的内容
通过指定arg[0]=“bar”
,可以成功地将值“bar”
分配给参数数组的第一个元素。但这对a
没有影响
见:
args[]
是匿名MethodMap实例中的一个局部变量,它引用一个临时数组,隐式创建该数组以保存.invoke(…)
调用的额外参数
分配args[0]
时要做的就是更新临时数组
void foo(){
//a是foo()方法中的局部变量,它引用
//值为“foo”的不可变字符串对象。
字符串a=“foo”;
addMethod(“1”,新方法(){
@凌驾
//args是execute()方法中的一个局部变量,该方法引用
//指向临时数组对象。
公共void执行(对象…参数){
//此赋值将更改临时变量的第0个元素
//数组指向值为“bar”的字符串对象。
args[0]=“条形”;
}
} );
//编译器将MethodMap.invoke()调用转换为:
//数组tmp=新数组[1];
//tmp[0]=a;//tmp[0]现在引用与a相同的不可变字符串。
//方法映射调用(“1”,tmp);
//调用返回后,tmp数组将被忽略。
方法映射调用(“1”,a);
系统输出打印项次(a);
}
Wow。。。我完全把事情搞砸了。天哪,我觉得自己很愚蠢。所以我在它周围创建了一个包装,然后通过包装修改它?@Gikkman:这根本不是一个愚蠢的错误;其他一些语言支持这一点很好!是的,您可以在它周围创建一个包装器,这将起作用(如果您想要一个现成的包装器,那么AtomicReference
concurrency helper可能是合适的)。。。我很确定我以前在课本上见过这种模式。好的,谢谢你的快速回答:-)顺便说一句,你的代码看起来非常像一个。您可能想看看一些AOP解决方案以获得灵感(或者改用它)。
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);
}