[JAVA] Anonyme Klasse (mit dem Ziel, Stream-API einzuführen)

Zweck

Ich fand es wichtig, das Konzept des Entwerfens und Implementierens anonymer Klassen zu verstehen, um Stream-API zu lernen. Entwurf unter Verwendung von Methodenreferenzen, funktionalen Schnittstellen, Lambda-Ausdrücken und Generika (Instanzbereich und Methodenbereich, Entwurf basierend auf PECS-Prinzipien) Informieren Sie sich vor dem Lernen über anonyme innere Klassen, die als Gateway dienen.

Verschachtelte Klasse

In Blöcken ({}) deklarierte Klassen werden als "Nasted Classes" bezeichnet.

image.png 入れ子クラスのイメージ図.

NastedClazzSample.java


public class NastedClazzSample {
	static class StaticClazz {}     //static member class

	class MemberClazz {}			//menber class  (inner class)

	void method() {
		class LocalClazz {}			//local class   (inner class)
	}
}

Verschachtelte Klassen, die als Mitgliedsklassen deklariert sind, können Zugriffsmodifikatoren haben

NastedClazzSample.java


public class NastedClazzSample {
	static protected class StaticClazz {} // OK

	private class MemberClazz {}          // OK

	void method() {
		public class LocalClazz {}        // NG
	}
}

Error.java


Das Qualifikationsmerkmal für die lokale Klasse LocalClazz ist falsch. Nur abstrakt oder endgültig erlaubt NastedClassSample.java	/...(path)Zeile 11 Java-Problem

Aus irgendeinem Grund. Der Umfang lokaler Klassen ähnelt lokalen Variablen Greifen Sie im Beispiel über method () auf LocalClazz zu. Mit anderen Worten, es ist dasselbe wie der Accessor von method (), daher ist es nicht möglich, es zu beschreiben. </ Font>

Innere Klasse

Wie oben erwähnt, werden andere verschachtelte Klassen (nicht statische Elementklassen) als statische Elementklassen als innere Klassen bezeichnet.

Merkmale der inneren Klasse

  • ① Kann keine statischen Elemente haben
  • (2) Zugriff auf Instanzvariablen, die in externen Klassen definiert sind
① Kann keine statischen Elemente haben

Nicht statische Mitglieder sind Instanzen zugeordnet Lokale Variablen werden im Stapelbereich verwaltet und im Heapbereich platziert, wenn die Zielklasse instanziiert wird.

InnerClazzSample.java


public class InnerClazzSample {
	public class Inner {
		String foo;
	}

	public static void main(String... args) {
		Inner inner = new InnerClazzSample().new Inner();
		inner.foo = "bar";
		System.out.println(inner.foo);
	}
}

Ausführungsergebnis.java


bar

Bei Verwendung ohne Instanziierung

InnerClazzSample.java


public class InnerClazzSample {
	public class Inner {
		String foo;
	}

	public static void main(String... args) {
		Inner.foo = "bar";
	}
}

Error.java


Nicht statisches Feld Inner.Foo InnerClazzSample kann nicht statisch referenziert werden.java	/~(path)Zeile 9 Java-Problem

Was ist die Bedeutung davon.

Zunächst liest die JVM die von der Anwendung verwendeten Klassen und erweitert sie im Speicher. Zu diesem Zeitpunkt befindet sich das statische Element in einem Speicherbereich (Klassenbereich), der sich vom nicht statischen Element unterscheidet. Der Bootstrap-Klassenlader wird beim JVM-Start aufgerufen, aber anstatt alle Klassen zu laden, wird er geladen, wenn eine Klassenreferenz aus der Anwendung vorhanden ist. Sie können auch den Bereich der Klassensätze ändern, die geladen werden können, indem Sie -Xbootclasspath ändern.

statische Elemente sind Klassen zugeordnet. Der Zeitpunkt der Speichererweiterung hängt von der JVM-Implementierung ab. </ Font>

(2) Zugriff auf Instanzvariablen, die in externen Klassen definiert sind

Outer.java


public class Outer {
    private int foo;

    public class Inner {
        public int bar;
        private void method() {
            this.foo = Outer.this.bar;   // OK
        }
    }

    private void method() {
        this.foo = bar;                  // NG
    }
}

Die Instanzpriorität nicht statischer innerer Klassen ist ebenfalls

  • Lokale Variable des Anrufers
  • Instanzvariable der inneren Klasse
  • Externe Klasseninstanzvariablen

Outer.java


public class Outer {
	String foo = "outerclass-a";
	String bar = "outerclass-b";
	String baz = "outerclass-c";

	public class Inner {
		String foo = "innerclass-a";
		String bar = "innerclass-b";

		public void thread() {
			String foo = "thread-c";

			System.out.println(foo);
			System.out.println(bar);
			System.out.println(baz);

			System.out.println(this.foo);
			System.out.println(Outer.this.foo);
		}
	}

	public static void main(String... args) {
		new Outer().new Inner().thread();
	}
}

Ausführungsergebnis.java


thread-c
innerclass-b
outerclass-c
innerclass-a
outerclass-a

Anonyme Klasse (anonyme Klasse, anonyme innere Klasse)

Wenn Sie eine verschachtelte Klasse verwenden, kann diese als Klasse ohne Namen verwendet werden Solche verschachtelten Klassen werden "anonyme Klassen" genannt.

Wird hauptsächlich für folgende Zwecke verwendet

  • ① Wenn die Wiederverwendbarkeit der Verarbeitung gering ist und nur vor Ort erforderlich ist
  • ② Wenn der Verarbeitungscode kurz ist, aber viele Anpassungen vorgenommen werden

Anonyme Klasse-Syntax 1.text


neuer Typname() {
Implementierung abstrakter Methoden
}

Anonyme Klasse-Syntax 2.text



Typname Instanzname=neuer Typname() {
Implementierung abstrakter Methoden
}

Implementieren Sie zunächst die abstrakte Methode der Schnittstelle, ohne die anonyme Klasse zu verwenden.

Sample.java


interface FooInterface {                           //interface
	void method();                                 //abstract method
}

class BarClazz implements FooInterface {           //implemented class
	public void method() {
		System.out.println("Did Implementation");  //implemented abstract method
	}
}

public class Sample{                               //runner
	public static void main(String... args) {
		new BarClazz().method();                   //new instance
	}
}

Bei der Implementierung einer abstrakten Methode mit einer anonymen Klasse

Sample.java




interface FooInterface {
	void method();
}
                                                            //nothing inplemented class
public class Sample {
	public static void main(String... args) {
		FooInterface foo = new FooInterface() {				//anonymous class
			public void method() {
				System.out.println("Did Implementation");	//implemented abstract method
			}
		};													//semi-coron
		foo.method();										//instance.method()
	}
}

Ausführungsergebnis.java


Did Implementation

Praktisches Beispiel für eine anonyme Klasse

Betrachten Sie ein praktisches Beispiel einer anonymen Klasse

① Wenn die Wiederverwendbarkeit der Verarbeitung gering ist und nur vor Ort erforderlich ist

Definieren Sie eine Klasse, die Kundeninformationen verwaltet

ManagementClientInformation.java


public class ManagementClientInformation {
	public static class Client {
		private int id;
		private String name;

		Client(int id, String name) {
			this.id = id;
			this.name = name;
		}

		public int getId() {
			return this.id;
		}

		public String getName() {
			return this.name;
		}
	}

	public static void main(String... args) {
		List<Client> clientList = new ArrayList<>();
		clientList.add(new Client(1, "matsuda"));
		clientList.add(new Client(2, "tanaka"));
		clientList.add(new Client(3, "neko"));
		clientList.stream()
				.forEach(x -> System.out.println(x.getId() + " " + x.getName()));
	}
}

Ausführungsergebnis.java


1 matsuda
2 tanaka
3 neko

Betrachten Sie die folgenden Ereignisse

Sie sind Systemingenieur Während der Wartung / Reparatur gab es eine Anfrage eines Kunden Es wird angefordert, einen bestimmten Bildschirm in umgekehrter Reihenfolge der Kunden-ID zu sortieren Darüber hinaus ist es verboten, die Client-Klasse zu ändern, da Bedenken hinsichtlich der Auswirkungen auf das System und des Aufblähens bestehen.

⇒ Verwenden Sie eine anonyme Klasse

ManagementClientInformation.java


public class ManagementClientInformation {
	public static class Client {
		private int id;
		private String name;

		Client(int id, String name) {
			this.id = id;
			this.name = name;
		}

		public int getId() {
			return this.id;
		}

		public String getName() {
			return this.name;
		}
	}

	public static void main(String... args) {
		List<Client> clientList = new ArrayList<>();
		clientList.add(new Client(1, "matsuda"));
		clientList.add(new Client(2, "tanaka"));
		clientList.add(new Client(3, "neko"));

		Collections.sort(clientList, new Comparator<Client>() {
			public int compare(Client c1, Client c2) {
				return Integer.compare(c2.getId(), c1.getId());
			}
		});

		clientList.stream()
				.forEach(x -> System.out.println(x.getId() + " " + x.getName()));
	}
}

Ausführungsergebnis.java


3 neko
2 tanaka
1 matsuda

Am Ende

Als ich Stream API zum ersten Mal berührte, verstand ich den Inhalt überhaupt nicht. Während ich es tat, vertiefte ich allmählich mein Verständnis, als ich die Methodenreferenz ⇒ Lambda-Ausdruck ⇒ Generika-Design in umgekehrter Reihenfolge lernte. Ich möchte es anwenden, nachdem ich den grundlegenden Teil fest verstanden habe.

Recommended Posts