2

I don't understand the difference between

this::myMethod  

and

ClassName::myMethod

when this is an instance of the ClassName class.

I thought that in both cases I invoke the method myMethod and give myObject that I run on as argument to the myMethod method, but I think there is a difference. What is it?

Eran
  • 387,369
  • 54
  • 702
  • 768
T.S
  • 911
  • 8
  • 24
  • instance vs class method.. one place you are executing myMethod on this instance where as in other you execute myMethod on Class – SMA Oct 02 '17 at 07:05
  • https://stackoverflow.com/questions/5666134/what-is-the-difference-between-class-this-and-this-in-java might help. – Naman Oct 02 '17 at 07:06
  • It depends on the context. The first one invokes myMethod on `this`. The second one invokes the static method myMethod of ClassName, or the instance method on the argument of the functional interface method (like in `stream.forEach(ClassName::myMethod)`, which would be equivalent to `stream.forEach(obj -> obj.myMethod())`. – JB Nizet Oct 02 '17 at 07:07
  • but when i use String::toUpperCase i execute myMethod which is toUpperCase on instance, not class – T.S Oct 02 '17 at 07:07
  • Possible duplicate of [What is the difference between Class.this and this in Java](https://stackoverflow.com/questions/5666134/what-is-the-difference-between-class-this-and-this-in-java) – Naman Oct 02 '17 at 07:10

1 Answers1

6

this::myMethod refers to myMethod on a specific instance of ClassName - the instance that you put this::myMethod in its code.

ClassName::myMethod can refer to either a static method or an instance method. If it refers to an instance method, it may be executed on a different instance of ClassName each time it is called.

For example:

List<ClassName> list = ...
list.stream().map(ClassName::myMethod)...

will execute myMethod each time for a different ClassName member of the list.

Here's a mode detailed example that shows the difference between these two type of method reference:

public class Test ()
{
    String myMethod () {
        return hashCode() + " ";
    }
    String myMethod (Test other) {
        return hashCode() + " ";
    }
    public void test () {
        List<Test> list = new ArrayList<>();
        list.add (new Test());
        list.add (new Test());
        System.out.println (this.hashCode ());
        // this will execute myMethod () on each member of the Stream
        list.stream ().map (Test::myMethod).forEach (System.out::print);
        System.out.println (" ");
        // this will execute myMethod (Test other) on the same instance (this) of the class
        // note that I had to overload myMethod, since `map` must apply myMethod
        // to each element of the Stream, and since this::myMethod means it
        // will always be executed on the same instance of Test, we must pass
        // the element of the Stream as an argument
        list.stream ().map (this::myMethod).forEach (System.out::print);
    }
    public static void main (java.lang.String[] args) { 
        new Test ().test ();
    }
}

Output:

2003749087 // the hash code of the Test instance on which we called test()
1747585824 1023892928  // the hash codes of the members of the List
2003749087 2003749087 // the hash code of the Test instance on which we called test()
Eran
  • 387,369
  • 54
  • 702
  • 768
  • So when we use this::myMethod, we invoke the method on the this object and we pass the each object from the collection as an argument to the method? – T.S Oct 02 '17 at 07:48
  • @T.S That's one example of using `this::myMethod`. I'm not sure it's a good example, since when we call `map` we usually want to transform an element of the Stream into some other type, so it would make more sense to use Test::myMethod (i.e. execute the method on each element of the Stream). – Eran Oct 02 '17 at 07:54