-2

Java 8

public class OidDTO {
    private String value;

    public OidDTO(String value) {
        this.value = value;
    }
}

Here Junit test:

  @Test
    public void change_object_by_ref() {
        OidDTO oidDTO = new OidDTO("init_value");
        changeOidDTO(oidDTO);

        String expected = "new_value";
        String actual = oidDTO.getValue();
        
        assertEquals(expected, actual);
    }

    private void changeOidDTO(OidDTO oidDTO) {
        oidDTO.setValue("new_value");
    }

As result the test is pass because expected and actual are equals. It's equals because in the method changeOidDTO I change value.

Nice.

Now another test:

 @Test
    public void change_object_by_ref() {
        OidDTO oidDTO = new OidDTO("init_value");
        changeOidDTO(oidDTO);

        String expected = "new_value";
        String actual = oidDTO.getValue(); // Why no NPE

        assertEquals(expected, actual);
    }

    private void changeOidDTO(OidDTO oidDTO) {
        oidDTO = null;
    }

And test is fail.

expected: <new_value> but was: <init_value>
Expected :new_value
Actual   :init_value

As you can see I set null in this line:

oidDTO = null;

The question is: Why not throw NPE in the next line:

String actual = oidDTO.getValue()

?

Alexei
  • 14,350
  • 37
  • 121
  • 240
  • 1
    You change the value copied in. Not the variable it was copied from. – Thorbjørn Ravn Andersen Dec 14 '21 at 20:39
  • @ThorbjørnRavnAndersen But I think that create copy of variable only when pass primitive type. When pass object then pass reference. Right? – Alexei Dec 15 '21 at 07:25
  • You get a copy of the reference to the object. Changing the copy of the reference does not change the original reference. – Thorbjørn Ravn Andersen Dec 15 '21 at 10:48
  • @ThorbjørnRavnAndersen But original and copy references are point the the SAME ONE object in the heap. So when I change this one object then it affects on all references (original and copy). Right? – Alexei Dec 15 '21 at 10:58
  • 1
    No. This is one of the things it is really hard to understand correctly in programming. The value passed in is a _reference_ to an object (called pointer in other languages) and is a _copy_ of the value held by the caller. You now have two references to the same object who have no idea of each other. Changing one of them does not influence the other. The object referenced is not even involved. I would suggest reading a very good tutorial on this, because this is really difficult to understand. It was probably the hardest for me to understand when I first encountered it in Pascal. – Thorbjørn Ravn Andersen Dec 15 '21 at 11:10

1 Answers1

1

You asked why no NPE on this line

    String actual = oidDTO.getValue(); // Why no NPE

Because oidDTO is not null.

    OidDTO oidDTO = new OidDTO("init_value");

This line

changeOidDTO(oidDTO);

Changes the LOCAL variable oidDTO, and not the original one being passed to the function.

hfontanez
  • 5,774
  • 2
  • 25
  • 37
  • But I think that when pass primitive pass as param to method, then create COPY of variable. But when pass object then pass reference (not pass copy of variable). Right? – Alexei Dec 15 '21 at 07:24
  • 1
    Java doesn't pass by reference. That means that the `oidDTO` passed to `changeOidDTO()` is not a pointer, but a copy of the original. When the method completes, that variable is no longer accessible. – hfontanez Dec 15 '21 at 12:09
  • 1
    @a_subscriber don't forget to check my answer if I answered your question satisfactory ;) – hfontanez Dec 15 '21 at 14:10