Story has multiple aspects: - Avoid inventing a class name - Next: now that we have an instance of an anonymous class defined in the scope of another method, could we allow access to the variables from the environment? What could it be useful for? - Then: what do we have to be careful about? (mutable data)
- Java reference types marked as `@FunctionalInterface` > This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Graphics 1.0 ```java public class Swing1 extends Frame { int count = 0; public Swing1 () { Button button = new Button ("Go"); add (button); Label out = new Label ("000", Label.CENTER); add (out); button.addActionListener (new MyActionListener(this, out)); // set size, layout, visible etc. } } ``` ```java class MyActionListener implements ActionListener { private Swing1 parent; private Label out; public MyActionListener (Swing1 parent, Label out) { this.parent = parent; this.out = out; } public void actionPerformed (ActionEvent e) { parent.count += 1; out.setText (String.format ("%03d", parent.count)); out.repaint (); } } ``` --- # <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Graphics 1.1 ```java public class Swing2 extends Frame { private int count = 0; public Swing2 () { Button button = new Button ("Go"); add (button); Label out = new Label ("000", Label.CENTER); add (out); // nested anonymous class button.addActionListener (new ActionListener() { public void actionPerformed (ActionEvent e) { count += 1; out.setText (String.format ("%03d", count)); out.repaint (); } }); } } ``` --- <!-- # <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Threads 1.0 ```java class Run1 { public static void main (String[] args) { for (int i = 0; i < 5; i++) { new Thread (new MyRunnable (i)).start (); } } } ``` ```java class MyRunnable implements Runnable { private int x; public MyRunnable (int x) { this.x = x; } public void run () { while (true) System.out.print (x); } } ``` ```sh 3331100000000000000000000000000022222222222222224444222... ``` ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Threads 1.1 ```java class Run5 { public static void main (String[] args) { for (int i = 0; i < 5; i++) { new Thread (new Runnable () { public void run () { while (true) System.out.print (i); } }).start (); } } } ``` * Compile error ```sh Run5.java:7: error: local variables referenced from an inner class must be final or effectively final System.out.print (i); ^ ``` ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Threads 1.1 ```java class Run2 { public static void main (String[] args) { for (int i = 0; i < 5; i++) { int x = i; new Thread (new Runnable () { public void run () { while (true) System.out.print (x); } }).start (); } } } ``` ```sh 3331100000000000000000000000000022222222222222224444222... ``` ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Some Languages Allow Mutable Variables - Perl (old versions) ```perl use threads; my $i; for ($i = 0; $i < 5; $i++) { my $th = threads->create (sub { while (1) { print $i; } }); $th->detach(); } sleep (1); ``` ```sh 5555555555555555555555555555555555555555555555555555555... ``` --- # <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Some Languages Allow Mutable Variables - Perl (old versions) ```perl use threads; my $i; for ($i = 0; $i < 5; $i++) { my $x = $i my $th = threads->create (sub { while (1) { print $x; } }); $th->detach(); } sleep (1); ``` ```sh 3331100000000000000000000000000022222222222222224444222... ``` --- # <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Some Languages Allow Mutable Variables - Perl 5 ```perl use threads; my $i; for ($i = 0; $i < 5; $i++) { my $th = threads->create (sub { while (1) { print $i; } }); $th->detach(); } sleep (1); ``` ```sh 000000000000002222222222222211111111111111111133333333333333444444444444444444... ``` ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Explicit Java 1.0 implementation ```java for (int i = 0; i < 5; i++) { new Thread (new MyRunnable (i)).start (); } ``` ```java class MyRunnable implements Runnable { private int x; public MyRunnable (int x) { this.x = x; } public void run () { while (true) System.out.print (x); } } ``` ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Java Functional Interface - Java 8 introduced <i>lambda expressions</i> - How to integrate this new feature with older APIs? <div class="grid grid-cols-2 gap-4"> <div> Java Anonymous Class and Instance ```java button.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { // do something on click } }); ``` </div> <div> Java Lambda Expression ```java button.addActionListener(e -> { // do something on click }); ``` </div> </div> - Java reference types marked as `@FunctionalInterface` > This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. ---
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Collections Processing - Java `map` method takes a `Function` ```java package java.util.stream; interface Stream<T> { ... // Returns a stream consisting of the results of applying // the given function to the elements of this stream <R> Stream<R> map (Function<? super T,? extends R> mapper); ... } ``` --- # <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Collections Processing - Provide `Stream` view of `List` in order to use map ```java public class Nested { public static void main (String[] args) { List<Integer> l = new ArrayList<> (); Stream<Integer> s = l.stream(); l.add (1); l.add (2); l.add (3); s.map (x -> x + 1) .collect (Collectors.toList ()) .forEach (x -> System.out.format ("%2d ", x)); } } ``` ```sh 2 3 4 ``` ---