4

I am a little confused with Java "All passings by value" concept.

Consider the following code:

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

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

can I code the SetVar function in the way that the following code sets A to 2 and B to Hi??

void Init() {
    SetVar(this.A, 2);
    SetVar(this.B, "Hi");
}
MBZ
  • 26,084
  • 47
  • 114
  • 191
  • No, you can't do that. You are passing the value of A to the method, which is likely null. So you are passing (null, 2) and (null, "Hi"), which isn't very useful. – Robert Hanson Oct 15 '12 at 12:01
  • Please follow the [Java naming conventions](http://www.oracle.com/technetwork/java/javase/documentation/codeconvtoc-136057.html). – Frank Pavageau Oct 15 '12 at 12:05

7 Answers7

2

Yes you can. By using reflection 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");
    }
  }
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
2

To put it in a nutshell, reassigning a value (meaning with = operator) to an existing reference does not change the object pointing by the original reference.

A big misunderstood in Java is that folks think that they are two types of variables:

  • Primitives (like int, boolean etc...)
  • References (like Integer, Boolean, custom objects etc...)

Java NEVER uses references. The word Reference is misnomer.

Java only uses Pointers instead for manipulating objects.

To better understand the shade: http://javadude.com/articles/passbyvalue.htm

Regarding your case, even though you skipped the Java Naming Conventions (but it's another subject), you could solve your "issue" by doing:

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

Indeed, if you pass A as a local parameter (as you did), this local parameter will represent a copy of the A reference since Java is only focused on passed-by-value. So changing it does not affect the initial reference.

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • Even if it is a name problem, pointer in C and Java are not the same possibilities : they are unmodifiable, they do not give direct access to memory, so Reference, for non mathematician is truelly a good answer, even if it do not smell good for academician – cl-r Oct 15 '12 at 12:23
  • @cl-r Yes, totally agree. But your explanation is deeper and would exceed the basic explanation, I think. It would be better if they could change the name by a mixed of pointer and reference, why not "poinref" ^^ – Mik378 Oct 15 '12 at 12:26
  • 1
    Greet, in French, the word "référence" and the action "faire référence à quelque chose" (refer to something) is exactly the usual mining. poinref may be good, perhaps `referencer`, the "person/actor" who hold a reference ? – cl-r Oct 15 '12 at 12:36
1

In general it depends. In this particular case, A and B being immutable, you can't.

If you had a mutable object with setters, you could mutate some of its properties in your setVar method:

var.setValue(value);

But you would not be able to change the reference that the original object points to (because it has been passed by value).

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

More about it in this post, which is part of the Java FAQ.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
1

Yes, Java is pass-by-value, but you must also realize that when you pass an object to a certain method, you are in fact passing a reference (pointer) to that object. In your case, the two arguments A and B are also immutable, meaning that you can only reassign the local variable that represents them, rather than replace the original objects that were passed in to SetVar.

nickolayratchev
  • 1,136
  • 1
  • 6
  • 15
0
void SetVar(Object??? var, Object value) {

become

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

Initialize in constructor :

Test (final Integer var, final String value){
   setVar(var, value);
} 
cl-r
  • 1,264
  • 1
  • 12
  • 26
0

Integer and String are immutable, so you cannot change the value of A or B after initialization, you simply assign a new value to the variable. And since once inside SetVar the variable var is local to the method, changing the object that is pointed by var does not affect outside callers.

vainolo
  • 6,907
  • 4
  • 24
  • 47
0

You can't do that because in your example you are passing this.A to the setVar() method, and this.A is null, so that isn't useful. What you can do however is have this.A be a holder, and pass the holder to the setVar() method.

The code below will do what you want. It uses an IntegerHolder and StringHolder for your fields a and b, and initializes the holder fields on construction of the class with empty holder objects.

Calling setVar() then doesn't set the value of the fields a and b, it instead sets the contents of the holders.

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;
    }

}
Robert Hanson
  • 579
  • 2
  • 7