4

我对Java“所有按值传递”的概念有点困惑。

考虑以下代码:

class Test {
    Integer A;
    String B;
    ...

    void SetVar(Object??? var, Object value) {
        // Set A variable to the value (considering that it's possible)
    }
}

我可以按照以下代码设置为和的SetVar方式对函数进行编码吗?A2BHi

void Init() {
    SetVar(this.A, 2);
    SetVar(this.B, "Hi");
}
4

7 回答 7

2

是的你可以。通过使用反射 java api。

class Test{
    void SetVar(Field field, Object value) throws 
                       IllegalArgumentException,IllegalAccessException {
         field.set(this, value);
    }

    public static void main(String[] args){
     Test test =new Test();
         test.SetVar(Test.class.getDeclaredField("A"), 2);
         test.SetVar(Test.class.getDeclaredField("B"), "Hi");
    }
  }
于 2012-10-15T12:12:21.650 回答
2

简而言之,将值(使用=运算符的含义)重新分配给现有引用不会更改原始引用指向的对象。

Java 中一个很大的误解是人们认为它们是两种类型的变量:

  • 基元(如 int、boolean 等...)
  • 引用(如整数、布尔值、自定义对象等...)

Java从不使用引用。参考这个词用词不当。

Java 仅使用指针来代替操作对象。

为了更好地理解阴影:http: //javadude.com/articles/passbyvalue.htm

关于您的情况,即使您跳过了 Java 命名约定(但这是另一个主题),您也可以通过以下方式解决您的“问题”:

void SetVar(Integer value) {
        this.A = value;
}

实际上,如果您A作为本地参数传递(如您所做的那样),则此本地参数将表示引用的副本,A因为 Java 仅关注passed-by-value. 所以改变它不会影响初始参考。

于 2012-10-15T12:12:55.600 回答
1

一般来说,这取决于。在这种特殊情况下,A 和 B 是不可变的,你不能。

如果你有一个带有 setter 的可变对象,你可以在你的setVar方法中改变它的一些属性:

var.setValue(value);

但是您将无法更改原始对象指向的引用(因为它已按值传递)。

var = someOtherObject; //no effect on the reference in the calling code

这篇文章中有更多关于它的信息,它是Java FAQ的一部分。

于 2012-10-15T12:00:37.710 回答
1

是的,Java 是按值传递的,但是您还必须意识到,当您将对象传递给某个方法时,实际上是在传递对该对象的引用(指针)。在您的情况下,这两个参数AB也是不可变的,这意味着您只能重新分配代表它们的局部变量,而不是替换传入的原始对象SetVar

于 2012-10-15T12:06:01.713 回答
0
void SetVar(Object??? var, Object value) {

变得

void SetVar(final Integer var, final String value) {
   A=var; // use minuscule for field like  a=var;
   B=value; // this. is not necessary here
}

在构造函数中初始化:

Test (final Integer var, final String value){
   setVar(var, value);
} 
于 2012-10-15T12:04:11.950 回答
0

Integer并且String是不可变的,因此您无法更改AB初始化后的值,您只需为变量分配一个新值。并且由于一旦SetVar变量内部var是方法的局部变量,更改指向的对象var不会影响外部调用者。

于 2012-10-15T12:04:14.273 回答
0

您不能这样做,因为在您的示例中,您将 this.A 传递给 setVar() 方法,而 this.A 为空,因此没有用。但是,您可以做的是让 this.A 成为持有者,并将持有者传递给 setVar() 方法。

下面的代码将做你想做的事。它为您的字段 a 和 b 使用 IntegerHolder 和 StringHolder,并在使用空持有人对象的类的构造时初始化持有人字段。

然后调用 setVar() 不会设置字段 a 和 b 的值,而是设置持有者的内容。

public class Test
{
    IntegerHolder a = new IntegerHolder();
    StringHolder b = new StringHolder();

    void setVar(IntegerHolder var, Integer value) {
        var.value = value;
    }

    void setVar(StringHolder var, String value) {
        var.value = value;
    }

    class IntegerHolder
    {
        Integer value;
    }

    class StringHolder
    {
        String value;
    }

}
于 2012-10-15T12:14:14.900 回答