[JAVA] Classe anonyme (visant à introduire l'API de flux)

Objectif

J'ai senti qu'il était essentiel de comprendre le concept de conception et d'implémentation de classes anonymes afin d'apprendre les API de flux. Conception à l'aide de références de méthode, d'interfaces fonctionnelles, d'expressions lambda et de génériques (étendue d'instance et portée de méthode, conception basée sur les principes PECS) Découvrez les classes internes anonymes qui servent de passerelle avant d'apprendre.

Classe imbriquée

Les classes déclarées dans des blocs ({}) sont appelées "Nasted Classes"

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)
	}
}

Les classes imbriquées déclarées comme classes membres peuvent avoir des modificateurs d'accès

NastedClazzSample.java


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

	private class MemberClazz {}          // OK

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

Error.java


Le qualificatif de la classe locale LocalClazz est incorrect. Seul résumé ou final autorisé NastedClassSample.java	/...(path)Problème Java de ligne 11

Pour certaines raisons. La portée des classes locales est similaire à celle des variables locales Dans l'exemple, accédez à LocalClazz via la méthode () En d'autres termes, c'est le même que l'accesseur de method (), il n'est donc pas possible de le décrire. </ Font>

Classe intérieure

Comme mentionné ci-dessus, les classes imbriquées (classes membres non statiques) autres que les classes membres statiques sont appelées classes internes.

Fonctionnalités de classe interne

  • ① Impossible d'avoir des membres statiques
  • (2) Accès aux variables d'instance définies dans les classes externes
① Impossible d'avoir des membres statiques

Les membres non statiques sont associés à des instances Les variables locales sont gérées dans la zone de pile et placées dans la zone de tas lorsque la classe cible est instanciée.

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);
	}
}

Résultat d'exécution.java


bar

Lorsqu'il est utilisé sans instanciation

InnerClazzSample.java


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

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

Error.java


Champ non statique Intérieur.Impossible de référencer statiquement foo InnerClazzSample.java	/~(path)Problème Java Line 9

Qu'est-ce que cela veut dire.

Tout d'abord, la JVM lit les classes utilisées par l'application et les étend en mémoire. À ce stade, le membre statique est placé dans une zone de mémoire (zone de classe) différente du membre non statique. Le chargeur de classe bootstrap est appelé au démarrage de la JVM, mais au lieu de charger toutes les classes, il est chargé lorsqu'il existe une référence de classe de l'application. Vous pouvez également modifier la plage d'ensembles de classes pouvant être chargés en modifiant -Xbootclasspath.

les membres statiques sont associés à des classes. Le moment de l'extension en mémoire dépend de l'implémentation JVM. </ Font>

(2) Accès aux variables d'instance définies dans les classes externes

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
    }
}

En outre, la priorité d'instance des classes internes non statiques est

  • Variable locale de l'appelant
  • Variable d'instance de classe interne
  • Variables d'instance de classe externes

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();
	}
}

Résultat d'exécution.java


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

Classe anonyme (classe anonyme, classe interne anonyme)

Lors de l'utilisation d'une classe imbriquée, elle peut être utilisée comme classe sans nom Ces classes imbriquées sont appelées "classes anonymes"

Principalement utilisé aux fins suivantes

  • ① Lorsque la réutilisabilité du traitement est faible et qu'il n'est nécessaire que sur place
  • ② Lorsque le code de traitement est court mais qu'il y a beaucoup de personnalisation

Classe anonyme-Syntaxe 1.text


nouveau nom de type() {
Implémentation de méthodes abstraites
}

Classe anonyme-Syntaxe 2.text



Nom du type Nom de l'instance=nouveau nom de type() {
Implémentation de méthodes abstraites
}

Tout d'abord, implémentez la méthode abstraite de l'interface sans utiliser la classe anonyme.

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
	}
}

Lors de l'implémentation d'une méthode abstraite à l'aide d'une classe anonyme

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()
	}
}

Résultat d'exécution.java


Did Implementation

Exemple pratique de classe anonyme

Prenons un exemple pratique de classe anonyme

① Lorsque la réutilisabilité du traitement est faible et qu'il n'est nécessaire que sur place

Définir une classe qui gère les informations client

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()));
	}
}

Résultat d'exécution.java


1 matsuda
2 tanaka
3 neko

Considérez les événements suivants

Vous êtes ingénieur système Il y avait une demande d'un client lors de la maintenance / réparation Il y a une demande pour trier un certain écran dans l'ordre inverse de l'identifiant client De plus, il est interdit de modifier la classe Client en raison de problèmes d'impact sur le système et de ballonnement.

⇒ Utiliser une classe anonyme

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()));
	}
}

Résultat d'exécution.java


3 neko
2 tanaka
1 matsuda

À la fin

Quand j'ai touché l'API Stream pour la première fois, je ne comprenais pas du tout le contenu. Pendant que je le faisais, j'ai progressivement approfondi ma compréhension en apprenant la méthode de référence ⇒ expression lambda ⇒ conception générique dans l'ordre inverse. Je voudrais l'appliquer après avoir bien compris la partie de base.

Recommended Posts