-1

The following is an example class

public class Utils {
    private static Function<String,Type2> typeFunc = null;

    public static void setTypeFunction(Function<String,Type2> func) {
    Utils.typeFunc = func;
    }

    public static Type2 getTypeFuncResult(String input) {
       return Utils.typeFunc.apply(input);
    }

}

And then the calling class

// Other code
String input = dummy;

// Setup func
Function<String,Type2> testFunc = s->new Type2(s);

// Call - it's all good
Utils.setTypeFunction(testFunc);
Utils.getTypeFuncResult(input);

// Nullify the func lambda output
testFunc = s->null;

// Now call again
Utils.getTypeFuncResult(input);  // Expected NULL, but still gets a Type2 object

I am trying to understand this in the context of the following:

a) Reference change for testFunc is not visible to static Utils.typeFunc- this means memory is probably being wasted without me knowing.

b) Lambda's are evaluated differently with reference to static references.

c) Anything else.

I believe this is more rudimentary Java, but was wondering if I can get any pointers.

UPDATE

I know java to be pass-by-"copy of the value of" reference. But here is the thing for comparisoni:

TypeA class:

public class TypeA {

    private int input = 0;

    public TypeA() {

    }

    public TypeA(int input) {
        this.input = input;
    }

    public void displayInput() {
        System.out.println(this.input);
    }

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

    public int getInput() {
        return this.input;
    }


}

TypeB Class:

public class TypeB {

    private TypeA typeA;

    public TypeB() {

    }

    public void setTypeA(TypeA typeA) {
        this.typeA = typeA;
    }

    public TypeA getTypeA() {
        return this.typeA;
    }

}

Now let's run a test

@Test
public void runReferenceTest() {
    TypeB typeB = new TypeB();
    TypeA typeA = new TypeA();
    typeB.setTypeA(typeA);
    System.out.println(typeB.getTypeA().getInput());  // should be 0
    typeA.setInput(2);
    System.out.println(typeB.getTypeA().getInput());  // Should be 2
    typeA = null; 
    System.out.println(typeB.getTypeA().getInput());   // Shows as 2

}

Based on the above, am I right to conclude that:

a) As long as the "copy" of the reference value is alive, the changes will get reflected.

b) If the reference is set to NULL, the copy will not get updated because it's a copy?

ha9u63a7
  • 6,233
  • 16
  • 73
  • 108
  • 2
    See [Is Java “pass-by-reference” or “pass-by-value”?](https://stackoverflow.com/q/40480/3890632) – khelwood Jan 23 '20 at 13:32
  • The **value** (which is a lambda function) currently held by your `testFunc` variable is passed to `setTypeFunction`. Whatever happens to the `testFunc` variable after that is irrelevant. Your `Utils` class has no relationship with the `testFunc` variable. – khelwood Jan 23 '20 at 13:34
  • a) how is memory wasted? b) no, they are not. c) what else? – Amadán Jan 23 '20 at 13:50
  • It seems that with POJO and non POJO designs, this pass-by-value analogy works differently. I have seen both the answers as well as my own experiment above. It seems like the behaviour will vary. – ha9u63a7 Jan 23 '20 at 14:32

2 Answers2

0

Not sure why you would expect the second call to Utils.getTypeFuncResult(input) to change its output. After all, you never called Utils.setTypeFunction(testFunc) with testFunc = s->null - so, Utils.typeFunc is still equal to s->new Type2(s).

You haven't provided information about Type2, but if Type2(null) is a valid constructor call, then it makes sense that the return value is the resulting Type2 object from that call.

Admittedly, I'm coming at this from a python background, where assigning a variable in any capacity means allocating new memory and pointing to something different, even if the variable already existed (a name is a reference, and changing the reference associated with a name does not change any other name that said reference was previously associated with) - and I have no idea how Java does things under the hood. But it looks like something is getting duplicated somewhere, and thus one way or another testFunc and Utils.typeFunc are not pointing at the same object once you've changed testFunc's value.

Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • Based on what I read, and also my own experiment - all the so called "Pass-By-Value/Reference" argument is subject to "Scopes" – ha9u63a7 Jan 23 '20 at 14:38
0

testFunc is just reference to the object it is currently holding. When you called Utils.setTypeFunction(testFunc); the referenced object was s -> new Type2(s). So this is what your static variable contains.

It does not matter that you pointed testFunc to a different object later.

Think of testFunc as a signpost–you're not suddenly being beamed to a different place, just because someone turned the signpost to a different direction after you passed it!

Amadán
  • 718
  • 5
  • 18