Pass-by Object Reference Wrapper to Method

Asked

Viewed 409 times

3

I have been researching about passing by reference in Java and realized that it is not possible to perform this procedure directly. As only object references and array’s can be passed by reference I thought to use the Wrapper classes to solve problems where I need to change an integer, for example, that is in main using a method. I did several tests but the change is never done properly. Where am I wrong? And what would be an alternative way to solve my problem?
Follow the code I made to perform these tests.

public class ReferenciaTeste {
    public static void main (String[] args)
    {
        Integer k = new Integer(1);

        System.out.println(k.toString()); //anterior à passagem

        ReferenciaTeste.muda(k);

        System.out.println(k.toString()); //depois da passagem

    }
}


public static void muda(Integer n)
{
    n = 3;
}

Exit:

1
1

2 answers

3

Explaining in detail your problem:

1 - When you create the object k, you allocate in memory an object that references this Integer.
2 - When you call the method muda(Integer n), you are declaring a Integer in the method muda. What does this mean? It means that by passing the variable k as a parameter of this method, the two (k and n) will be referencing the same object in memory.
3 - The problem is: from the moment you change the value of the variable n, this variable ceases to reference the same variable object k, referencing a new object Integer of value in your case, 3.

In short, any changes you make to Integer avowed within of the method muda(Integer n) will only have an effect on this same method, not influencing the external object that was passed as parameter.

How to solve
Create a class called, for example, IntegerWrapper and create an object of the type Integer, and add your getters and setters. That way, you’ll always be using the same object in your changes.
An example of how this Wrapper could be:

public class IntegerWrapper {
    private Integer i;

    public void setValue(Integer i) {
        this.i = i;
    }

    public Integer getValue() {
        return i;
    }
}
  • I did not understand why a change in the variable "n" will result in no longer referencing the same memory location that the variable "k" refers to. When I use an array, for example, and make changes to it, these changes happen in the same memory location and so I get the modified array in main().

  • 1

    Why are you not changing the variable n, and create a new instance of it. Whenever you use the = to define a value for a variable, you are creating a new instance of it. This instance is only valid for the current scope. Normally we change arrays in another method by changing some position of it, which is allowed because we are using the same instance, but if you try to define a new array using the =, you will see that it will remain unchanged when you exit the method in which you defined this new array.

  • 1

    I performed a quick test to check. I created an integer array (int[]) and populated with 20 values. After that, I passed this vector as a parameter to a method and changed the value of index 19 in this way: inteiros[19] = valor;, what works. Soon after, I changed this method and created a new vector that way: inteiros = new int[20];, and in this case the vector remained unchanged upon returning to the method main.

3


What happened

What happens logically after the first assignment is this:

inserir a descrição da imagem aqui

No matter what you used new Integer(1) or simply 1, the result is the same.

When you called the method muda, what happens is this:

inserir a descrição da imagem aqui

And finally, when the second assignment occurs, we have a new value for n:

inserir a descrição da imagem aqui

When the method muda ends, the variable n and the value 3 are discarded and the state remains the same as the first image.

What happens to an array

When using an array, you are actually referencing an object that contains several values:

inserir a descrição da imagem aqui

By passing it on to the method muda, you will have two variables pointing to the array:

inserir a descrição da imagem aqui

When changing an element, the two variables remain pointing to the same array, but the internal state of the array is affected, changing one of its values.

inserir a descrição da imagem aqui

Finally, after execution of the method, the variable k remains intact and unchanged, however, the internal state of the object it refers to was affected:

inserir a descrição da imagem aqui

Using a wrapper object

Danne’s response tells how you can use an object whose internal value can be affected.

I’m not going to draw this because it would be exactly the same sequence using the vector.

In fact, many people use vectors or maps as an easy way to modify parameters, but this is not very common or good practice.

Considerations

Immutable objects such as Integer and String and references that cannot be affected in the methods (such as C pointers) exist for a very simple reason: maintain the mental health of the developers.

I say this because although it leaves the language more restricted, it also avoids numerous problems where values are unexpectedly modified by obscure methods. In a language that claims to be easy and universal, this is a small price to pay.

Also, the basic solution for this case is extremely simple. Just return the modified object:

public static void main (String[] args) {
    Integer k = 1;
    Integer k1 = incrementa2(k);
    System.out.println(k1); 
}

public static Integer incrementa2(Integer n) {
    return n + 2;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.