Anonyme Innere Klassen in Java
Übungsfragen
Übungsfrage
Was ist die Ausgabe des folgende Programms?
- Main.java
public final class Main
{ int i = 3;public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( new Main().i ); }}
Übungsfrage
Was ist die Ausgabe des folgende Programms?
- Main.java
public final class Main
{ int i = 3;public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( new Main().i++ );
java.lang.System.out.println( new Main().i++ ); }}
Übungsfrage
Was ist die Ausgabe des folgende Programms?
- Main.java
public final class Main
{ int i = 3;public void m()
{ java.lang.System.out.println( i++ );
java.lang.System.out.println( this.i++ );
java.lang.System.out.println( Main.this.i++ ); }public void run()
{ Main m = new Main();
m.m();
m.m(); }public static void main( final java.lang.String[] args )
{ new Main().run(); }}
Exemplarerzeugungsausdruck für Standardklasse
Main.java
public final class Main
{ int i = 3;public static void main( final java.lang.String[] args )
{new java.lang.Object(); }}
transcript
Exemplarerzeugungsausdruck für anonyme innere Klasse
Die Implementation einer Schnittstelle durch die Klasse »Main« wurde schon in früheren Lektionen behandelt
Main.java
public final class Main implements java.lang.Runnable
{ public void run(){}
public static void main( final java.lang.String[] args )
{ }}
Im folgenden Beispiel wird die angegebene Schnittstelle »java.lang.Runnable« durch eine anonyme innere Klasse implementiert.
Dabei steht hinter dem Schlüsselwort »new« der Name der implementierten Schnittstelle. Dadurch wird eine neue anonyme Klasse deklariert, welche die angegebene Schnittstelle implementiert. Hinter der schließenden runden Klammer des Exemplarerzeugungsausdrucks folgt dann ein Klassenrumpf, in welchem Einträge (Exemplarmethoden, Exemplarfelder und auch statische final Felder) deklariert werden können, die dann zu der deklarierten anonymen Klasse gehören.
»java.lang.Runnable« ist nicht der Name der anonymen inneren Klasse, sondern gibt nur die von ihr implementierte Schnittstelle an.
Man kann sich hier »new java.lang.Runnable« als eine Abkürzung für »new implementation of java.lang.Runnable« oder »new instance of a class that implements java.lang.Runnable« vorstellen.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ new java.lang.Runnable(){ public void run(){} }; }}transcript
Ad-hoc Aufrufe
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{java.lang.System.out.println
( new java.lang.Object().toString() );new java.lang.Runnable()
{ public void run()
{ java.lang.System.out.println( "run" ); } }.run(); }}transcript
java.lang.Object@1db9742
run
Hinzufügen weiterer Felder und Methoden
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{new java.lang.Runnable()
{ static final int i = 2;public void q()
{ java.lang.System.out.println( i ); }public void run()
{ q(); } }.run(); }}transcript
2
Eigene und umgebende Felder
Main.java
public final class Main
{ int i = 3;public void run()
{ new java.lang.Runnable()
{ int i = 7;
public void run()
{ java.lang.System.out.println( i );
java.lang.System.out.println( this.i );
java.lang.System.out.println( Main.this.i ); }}.run(); }public static void main( final java.lang.String[] args )
{ new Main().run(); }}transcript
7
7
3
Mehrere anonyme innere Klassen
Main.java
public final class Main
{ int i = 3;public void run()
{ new java.lang.Runnable()
{ int i = 7;
public void run()
{ java.lang.System.out.println( i );
java.lang.System.out.println( this.i );
java.lang.System.out.println( Main.this.i ); }}.run();new java.lang.Runnable()
{ int i = 7;
public void run()
{ java.lang.System.out.println( i );
java.lang.System.out.println( this.i );
java.lang.System.out.println( Main.this.i ); }}.run(); }public static void main( final java.lang.String[] args )
{ new Main().run(); }}transcript
7
7
3
7
7
3- Darstellung
.------------------.
| :Main |
| ----- |
| i |
'------------------'
^
|
.-----------'-----------.
| |
| |
.------------------. .------------------.
| *Runnable | | *Runnable |
| --------- | | --------- |
| j | | j |
'------------------' '------------------'
Dies ist keine Vererbung. Die beiden anonymen inneren Klassen sind keine Unterklassen von Main.
Das Objekt »m« enthält zwei Implementation der Schnittstelle »java.lang.Runnable«, die beide auf die Felder von »m« zugreifen können. Damit implementiert »m« die Schnittstelle »java.lang.Runnable« praktische zwiefach!
--> zwei Implementation ein und derselben Schnittstelle innerhalb einer Klasse! Beide haben Zugriff auf die Felder der umgebenden Klasse.
Main.java
public final class Main
{ int i = 3;public void run()
{ new java.lang.Runnable()
{ int i = 7;
public void run()
{ java.lang.System.out.println( Main.this.i++ ); }}.run();new java.lang.Runnable()
{ int i = 7;
public void run()
{ java.lang.System.out.println( Main.this.i ); }}.run(); }public static void main( final java.lang.String[] args )
{ new Main().run(); }}transcript
3
4Main.java
public final class Main
{ int i = 3;public void run()
{final java.lang.Runnable r = new java.lang.Runnable()
{ int i = 1;
public void run()
{ java.lang.System.out.println( Main.this.i++ );
java.lang.System.out.println( this.i++ ); }};final java.lang.Runnable s = new java.lang.Runnable()
{ int i = 1;
public void run()
{ java.lang.System.out.println( Main.this.i++ );
java.lang.System.out.println( this.i++ ); }};r.run();
s.run();
r.run(); }
public static void main( final java.lang.String[] args )
{ new Main().run(); }}transcript
3
1
4
1
5
2
Vergleich mit externer Klassen
Main.java
class Runnable implements java.lang.Runnable
{ final Main main;
public Runnable( final Main main ){ this.main = main; }
public void run()
{ java.lang.System.out.println( this.main.i++ ); }}public final class Main
{ int i = 3;public void execute( final java.lang.Runnable runnable )
{ runnable.run(); }public void main()
{execute( new Runnable( this ) );
execute
( new java.lang.Runnable()
{ public void run()
{ java.lang.System.out.println( Main.this.i++ ); }} );}public static void main( final java.lang.String[] args )
{ new Main().main(); }}- Protokoll
3
4
TRG
Main.java
final class Acceptor
implements java.util.function.Consumer< java.lang.String >
{ @java.lang.Override
public void accept( final java.lang.String word )
{ java.lang.System.out.printf( "Tomaten%nRotkohl Gruenkohl%n%s%n", word ); }}public final class Main
{ public static void main( final java.lang.String[] args )
{ java.util.Arrays.asList( "Gurken", "Spinat", "Kohlrabi" ).
forEach( new Acceptor() ); }}- Protokoll
Tomaten
Rotkohl Gruenkohl
Gurken
Tomaten
Rotkohl Gruenkohl
Spinat
Tomaten
Rotkohl Gruenkohl
KohlrabiMain.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.util.Arrays.asList( "Gurken", "Spinat", "Kohlrabi" ).
forEach
( new java.util.function.Consumer< java.lang.String >()
{ @java.lang.Override
public void accept( final java.lang.String word )
{ java.lang.System.out.printf( "Tomaten%nRotkohl Gruenkohl%n%s%n", word ); }} ); }}- Protokoll
Tomaten
Rotkohl Gruenkohl
Gurken
Tomaten
Rotkohl Gruenkohl
Spinat
Tomaten
Rotkohl Gruenkohl
Kohlrabi
Übungsaufgaben
Übungsaufgabe
Ermitteln Sie mit Hilfe gängiger Standardmethoden den Namen der Klasse des Objektes »r« in dem folgenden Programm.
Main.java
public final class Main
{public void run()
{ final java.lang.Runnable r = new java.lang.Runnable()
{ public void run() {} }; }public static void main( final java.lang.String[] args )
{ new Main().run(); }}