4

What happens when the reference of a method which belongs to a variable is destroyed?

public class Hey{
    public double bar;

    public Hey(){
        bar = 2.0d;
    }

    public double square(double num){
        return Math.pow(num , bar);
    }
}

Function<Double, Double> square;
whatsGonnaHappen: {
    Hey hey = new Hey();
    square = hey::square;
}//is hey still kept around because its method is being referenced?

double ans = square.apply(23d);
Michael
  • 2,673
  • 1
  • 16
  • 27
  • have you tried calling a method after square? Why would it be gone? – Stultuske Oct 07 '15 at 21:13
  • 3
    What functional interface are you referring to, btw? – Stultuske Oct 07 '15 at 21:13
  • The `Function` interface located in java.util.function @Stultuske – Michael Oct 07 '15 at 21:14
  • 1
    How would `square.apply(23d)` work if the `Hey` instance was garbage collected? – Sotirios Delimanolis Oct 07 '15 at 21:19
  • 2
    The only thing that's happening is a refusal to compile. Could you provide an example that compiles and can pose the same question? – Makoto Oct 07 '15 at 21:20
  • You don’t need to deal with scopes at all: `DoubleUnaryOperator square = new Hey()::square;` creates a function bearing a reference to an instance of `Hey` to which no other references exist. Of course, that instance will not cease to exist, as that’s the whole point of a programming language with memory management; you can’t destroy an object that is still in use. – Holger Oct 08 '15 at 08:47

2 Answers2

11

Scope is a compile time concept that governs where names in source code can be used. From the JLS

The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is visible (§6.4.1).

The fact that the name hey is restricted to the body of the whatsGonnaHappen labeled statement doesn't have any bearing on whether the instance referenced by hey at runtime is a candidate for garbage collection (which I assume is what you're worried about).

Concerning the variable capture, yes, the method reference hey::square is a reference to an instance method of a particular object (the one referenced by hey) and will therefore capture the value of the variable hey when the method reference expression is evaluated to produce an instance and use it when apply is invoked.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
2

Your method reference is essentially equivalent to doing this:

Hey hey = new Hey();
Function<Double, Double> square = new DoubleDoubleFunction(hey);

where the class DoubleDoubleFunction is defined like this

class DoubleDoubleFunction implements Function<Double, Double> {
    private final Hey hey;

    public DoubleDoubleFunction(Hey hey) {
        this.hey = hey;
    }

    @Override
    public Double apply(Double num) {
        return hey.square(num);
    }
}

In other words, square holds a reference to the Hey.

I don't know about eclipse, but with IntelliJ you can easily translate method references and lambdas into anonymous / static nested / inner classes to see what's going on. I find this a very instructive thing to do.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • 2
    You can do that [in Eclipse](http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2FwhatsNew%2Fjdt_whatsnew.html) too, thanks for the discovery! – Luigi Cortese Oct 10 '15 at 10:02