I'm trying to read through this https://leanpub.com/whatsnewinjava8/read#leanpub-auto-scope and I'm a bit confused as to:
- why toString() is called in r1's assignment
- how this demonstrates the scope available to the lambda
I'm trying to read through this https://leanpub.com/whatsnewinjava8/read#leanpub-auto-scope and I'm a bit confused as to:
I can answer the first question with certainty:
When you call the function System.out.println, it will do the following:
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
Source: https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html#println-java.lang.Object-
And the subsequent call of String.valueOf(x) will do the following:
If the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
Source: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#valueOf-java.lang.Object-
Since this refers to an instance of Hello it will just call the Hello.toString() method on the given instance - callstack:
System.out.println(this);
String.valueOf(this);
this.toString();
The second question regarding the scope probably means that you can still refer to the methods and fields of the enclosing class, yet I find this example a weird and also not very well documented one.
In a lamdba, this refers to the class declaring the lambda, unlike an anonymous class where this this refers to the anonymous class.
For exemple :
public class Hello {
Runnable r1 = () -> out.println(this);
Runnable r2 = new Runnable() {
@Override
public void run() {
out.println(this);
}
};
public String toString() {
return "Hello, world!";
}
public static void main(String... args) {
new Hello().r1.run(); // Hello, world!
new Hello().r2.run(); // something like Hello$1@776ec8df
}
}
Whenever you define a toString method in a class:
class ArbitaryClass {
String toString() { System.out.println("Object of ArbitaryClass."); }
}
Then when you call System.out.println on an instance of it, toString method will be triggered:
System.out.println(new ArbitaryClass()); // Will print Object of ArbitaryClass.
So here when you are trying to run new Hello().r1.run(), it's just invoking out.println(this) which is, (this), a representation of the current object, (new Hello()), of class which in turn will invoke toString method and print the "Hello, world!" message.
And as long as you call out.println(this) or out.println(toString()) inside the class then lambda has access to its properties and methods.