2

I'm refactoring an SWT project I worked on some time ago, and I would like to use Java 8, now In the current version I have something like this:

       Runnable runnable = new Runnable() {
            public void run() {
                // do some stuff...
                Display.getCurrent().timerExec(1000, this);
            }
        };
       Display.getCurrent().timerExec(1000, runnable);

And I'm trying to use Java 8, like this:

       Runnable runnable2 = () -> { 
            // do some stuff...
            Display.getCurrent().timerExec(1000, this);
        };
        Display.getCurrent().timerExec(1000, runnable2);

The problem is in line:

Display.getCurrent().timerExec(1000, this);

"this" in the first code (not Java 8) is referring to the Runnable Object, in the second one is referring to the main class, indeed the error I get at compilation time is the following:

The method timerExec(int, Runnable) in the type Display is not applicable for the arguments (int, MainClass)

How can I fix this, in order to execute the timer?

EDIT: Looking in StackOverflow previous questions I found this: Lambda this reference in java

It seems is it not possible to refer to "this" in lambda, so I cannot use the SWT timer with lambda? is there a work around?

navy1978
  • 1,411
  • 1
  • 15
  • 35
  • I can think of a hack, but it doesn't really save on code that much (which seems to be the point of using the lambda in the first place?), and using an anonymous class is much clearer on communicating what you're doing any ways. – Jorn Vernee Jan 24 '18 at 00:11
  • Jorn, yes I know, inside the runnable I have other code using lambda I would like to have everything aligned, if it is possible. Now I’m curious , can you please provide the hack just for understand any possibility? – navy1978 Jan 24 '18 at 00:22
  • 1
    This: https://ideone.com/FKNRJR But now that I look again, it actually uses a few _more_ characters. – Jorn Vernee Jan 24 '18 at 00:30
  • Thank you, but it looks really ugly to me... – navy1978 Jan 24 '18 at 06:15

3 Answers3

4

I am not sure why you are trying to self reference inside lambda. It is usually a good practice to keep lambda expressions short and readable. Just call a private method from your lambda like this:

Display.getCurrent().timerExec( 1000, () -> process() );

private void process(){
    // do some stuff...
    Display.getCurrent().timerExec( 1000, () -> process() );
}
tsolakp
  • 5,858
  • 1
  • 22
  • 28
  • The problem here is that the SWT timer works like that so the external call execute the Runnable only once, and the call inside the Runnable re execute it self each time... you can find a minimal example here, not using Java 8: http://www.java2s.com/Tutorial/Java/0280__SWT/Createonerepeatingtimer.htm – navy1978 Jan 24 '18 at 17:43
  • 2
    Unless `Display.timerExec` requires user to pass same instance of Runnable (which I dont think is the case according to their javadoc) you can rewrite the code you linked using a private method. – tsolakp Jan 24 '18 at 17:52
  • Uhmmmm. I think you are right, I'm new to Lambda, so I'm learning, I cannot test it now, but I will do it asap, and if it works I thing this is the best solution till now... ;) – navy1978 Jan 24 '18 at 17:56
  • I think for my personal case, this is the more elegant and readable solution, thank you. – navy1978 Jan 24 '18 at 18:23
2

If you declare your Runnable as a local variable, then you can't reference the self Runnable instance from within the lambda.

However, if you declare the Runnable as an attribute of a class, then you can reference the Runnable instance from within the lambda:

class SomeClass {

    private Runnable runnable2 = () -> { 
        // do some stuff...
        Display.getCurrent().timerExec(1000, this.runnable2);
    };
}

You are the only one who knows if it's worth trying this approach...

fps
  • 33,623
  • 8
  • 55
  • 110
  • I think this is the more elegant solution here , more in general, but bad in my specific case... ;) – navy1978 Jan 24 '18 at 06:16
1

This is one 'workaround', but it makes things less clear than the original code. I would keep the original.

    Runnable[] runnable2 = {null}; 
    runnable2[0] = () -> { 
        // do some stuff...
        Display.getCurrent().timerExec(1000, runnable2[0]);
    };
    Display.getCurrent().timerExec(1000, runnable2[0]);
DHa
  • 659
  • 1
  • 6
  • 21
  • 2
    I gave you +1 because it is not elegant at all but it sound to me like: "f*ck the system!" :) LOL! – navy1978 Jan 24 '18 at 06:18