[JAVA] So erstellen Sie eine bequeme Methode, die Generika und eine funktionale Schnittstelle verwendet

Erstellen einer praktischen Methode

Bei der Entwicklung in Teams mit einer großen Anzahl von Personen kommt die Verarbeitung heraus, die Sie gemeinsam ausführen möchten. Zum Beispiel werden Zeichenfolgenoperationen und Datumsoperationen in verschiedenen Szenen verwendet, aber in diesem Fall denke ich, dass Sie eine praktische Bibliothek verwenden oder eine Klasse mit nützlichen Methoden erstellen werden.

Wenn es sich um einen Prozess für eine bestimmte Klasse handelt, kann er bis zu einem gewissen Grad leicht erstellt werden. Bei der Entwicklung mit einer großen Anzahl von Personen besteht jedoch die Anforderung, einen gemeinsamen Prozess für verschiedene Klassen durchzuführen.

Etwas, das zu dieser Zeit bequem zu verwenden ist, ist "Generika" oder "funktionale Schnittstelle". Selbst wenn Sie über diese beiden Dinge Bescheid wissen, kann es für manche Menschen schwierig sein, zu verstehen, wie sie tatsächlich verwendet werden.

Dieses Mal möchte ich Ihnen vorstellen, wie Sie es tatsächlich verwenden, während Sie den Prozess der tatsächlichen Erstellung einer praktischen Methode verfolgen.

Was ist Generika (generischer Typ)?

Indem Sie es wie einen Parameter an die Definition des Datentyps übergeben, können Sie ein Programm mit einer ähnlichen Struktur für mehrere Datentypen unterstützen.

Beispielsweise gab es bis JDK1.4 beim Umgang mit List keine Typspezifikation und alles konnte als Objekt eingegeben werden.

List list = new ArrayList();
list.add("string");
list.add(Integer.valueOf(100));

Wenn der Typ nicht eingeschränkt ist und Sie nur Zeichen eingeben möchten, muss die Person, die das Programm erstellt, vorsichtig sein. Nachdem die Generika herauskamen, wurde es möglich, den Typ anzugeben, und es wurde möglich, wie folgt zu schreiben.

List<String> list = new ArrayList<>();
list.add("string1");
list.add("string2");

In den Java-API-Spezifikationen werden sie als ** List \ <E > ** bzw. ** ArrayList \ <E > ** aufgeführt. Dieser ** E ** -Teil wird als Generics bezeichnet, und für Programme mit derselben Struktur kann ein beliebiger Typ festgelegt werden.

Was ist eine funktionale Schnittstelle?

Eine einfache Darstellung einer funktionalen Schnittstelle ist eine Schnittstelle, mit der Sie in Java 8 eingeführte "Methodenreferenzen" und "Lambda-Ausdrücke" zuweisen können.

Zum Beispiel werden Getter und Setter, die häufig in Java erstellt werden, durch eine funktionale Schnittstelle wie folgt dargestellt.

Methode Schnittstelle Methode
getter Supplier<T> T get​()
setter Consumer<T> accept(T t)

Supplier ist eine Schnittstelle, die keine Argumente hat und einen beliebigen Typ zurückgibt. Ähnliche Begleiter sind IntSupplier, BooleanSupplier usw., die eher Grundelemente als willkürliche zurückgeben.

Consumer ist eine Schnittstelle, die Argumente akzeptiert und keinen Rückgabewert hat. Es gibt auch IntConsumer, DoubleConsumer usw., die Grundelemente nicht willkürlich, sondern an ähnliche Peers übergeben.

Lassen Sie uns eine bequeme Methode für Unit-Tests erstellen

Für diejenigen, die noch nie Generika oder funktionale Schnittstellen verwendet haben, kann die obige Erklärung schwierig sein. Daher werde ich erklären, wie man es einfach benutzt, während man tatsächlich eine bequeme Methode erstellt.

Vorbereitung

Angenommen, Sie haben eine Schülerklasse erstellt. Es wird angenommen, dass die Schülerklasse eine Schulregistrierungsnummer, einen Schülernamen und ein Alter hat und Setter und Getter definiert sind.

public class Student {
    /**Schülernummer*/
    private String code;

    /**Name des Studenten*/
    private String name;
    
    /**Alter*/
    private int age;

    //... setter,Getter Abkürzung...
}

Um die Daten für den Komponententest vorzubereiten, erstellen wir drei Schüler als Testdaten und fügen sie in eine Liste ein.

final Student student1 = new Student();
student1.setCode("S01001");
student1.setName("Yamada Taro");
student1.setAge(20);

final Student student2 = new Student();
student1.setCode("S02001");
student1.setName("Jiro Yamada");
student1.setAge(19);

final Student student3 = new Student();
student1.setCode("S03001");
student1.setName("Saburo Yamada");
student1.setAge(18);

final List<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);

Wenn es für 3 Personen ist, kann ich es noch nicht sehen, aber wenn diese Zahl auf 10 oder 20 steigt, wird es eine große Sache sein.

Erstellen einer Methode, die das Erstellen einer Liste vereinfacht

Zuerst habe ich eine Methode erstellt, die das Erstellen von Listen vereinfacht.

public <T> List<T> createInstanceList(Supplier<T> supplier, int size) {
    return IntStream.range(0, size)
            .mapToObj(i -> supplier.get())
            .collect(toList());
}

Ich werde dieses Programm nach und nach erklären.

public <T> List<T> createInstanceList(Supplier<T> supplier, int size) 

In Bezug auf die Deklaration der Methode werden zunächst \ <T > und die Generika definiert. Da es Generika verwendet, ist es zu einer Methode geworden, die für jede Klasse verwendet werden kann.

Da der Rückgabetyp ** List \ <T > ** ist, wird eine Liste eines beliebigen Typs zurückgegeben.

Da das erste Argument als ** Lieferant \ <T > ** deklariert ist, können Sie eine Schnittstelle erhalten, um einen beliebigen Typ zurückzugeben, wie in der Einführung von Generics erwähnt.

Das erste Ladeargument ist ** int **, mit dem Sie die Größe der Liste angeben können.

IntStream.range(0, size)

Als nächstes wird der Wert zurückgegeben. Zuerst wird der Stream mit ** IntStream.range (0, Größe) ** erstellt. Wiederholen Sie diesen Vorgang von 0 bis Größe -1, da Sie den Bereich verwenden. Wenn die Größe 3 ist, werden die Zahlen 0, 1, 2 wiederholt.

.mapToObj(i -> supplier.get())

IntStream hat 0, 1, 2 früher bestanden, aber ich ignoriere es und verwende ** vendor.get () **. Dies ruft die get-Methode der als Argument übergebenen Funktionsschnittstelle auf und gibt das Ergebnis zurück.

.collect(toList());

Schließlich wird die Anzahl der Wiederholungen wiederholt (im Beispiel dreimal). Der von der Funktionsschnittstelle empfangene Wert wird in eine Liste gepackt und zurückgegeben.

Anwenden der Methode zur Vereinfachung der Liste

Da es einige Teile gibt, die schwer zu erklären sind, ändern wir den ersten Code, um zu sehen, wie sich diese Methode tatsächlich ändert.

final List<Student> students = createInstanceList(Student::new, 3);
students.get(0).setCode("S01001");
students.get(0).setName("Yamada Taro");
students.get(0).setAge(20);
students.get(1).setCode("S02001");
students.get(1).setName("Jiro Yamada");
students.get(1).setAge(19);
students.get(2).setCode("S03001");
students.get(2).setName("Saburo Yamada");
students.get(2).setAge(18);

Die Schülerinstanziierung und die Einstellung auf Liste sind weg.

final List<Student> students = createInstanceList(Student::new, 3);

In dieser ersten Zeile werden gleichzeitig eine Liste und eine interne Instanz erstellt. ** Student :: new ** wird als ** Konstruktorreferenz ** bezeichnet und gibt eine ** Funktionsschnittstelle ** zurück, die das Ergebnis von new Student () zurückgibt.

Die Konstruktorreferenz wird als Lieferant behandelt und als erstes Argument der zuvor erstellten Methode übergeben. Das Ergebnis von new Student () wird von vendor.get () zurückgegeben, das in der vorherigen Methode verwendet wurde.

Erstellen Sie eine Methode, um einen Wert für ein Objekt in List festzulegen

Ich habe die Methode früher erstellt und der Code ist kürzer, aber das Festlegen des Werts ist immer noch kompliziert. Daher werde ich den folgenden Code schreiben.

public <T, U> void setValues(List<T> obj, BiConsumer<T, U> biConsumer, U... values) {
    for (int i = 0; i < obj.size(); i++) {
        biConsumer.accept(obj.get(i), values[i]);
    }
}

Ich werde dieses Programm nach und nach erklären.

public <T, U> void setValues(List<T> obj, BiConsumer<T, U> biConsumer, U... values)

In Bezug auf die Deklaration der Methode werden zunächst ** \ <T, U > ** und die Generika definiert. Im Gegensatz zur ersten Methode werden zwei beliebige Typen behandelt.

Da der Rückgabetyp ** void ** ist, wird kein Wert zurückgegeben.

Da das erste Argument ** List obj ** ist, übergeben Sie eine Liste eines beliebigen Typs, für den Sie einen Wert festlegen möchten.

Das zweite Argument ist ** BiConsumer <T, U> biConsumer **. Dies wird später erklärt.

Das dritte Argument ist ** U ... Werte **, und variable Argumente können übergeben werden. Mit diesem Argument können Sie den Wert festlegen, den Sie für die Objekte in der List-Variablen festlegen möchten.

Methode für Wertesatz anwenden

Lassen Sie uns den Code ändern, um zu sehen, wie er sich ändert, wenn wir diese Methode tatsächlich verwenden.

final List<Student> students = createInstanceList(Student::new, 3);
setValues(students, Student::setCode, "S01001", "S02001", "S03001");
setValues(students, Student::setName, "Yamada Taro", "Jiro Yamada", "Saburo Yamada");
setValues(students, Student::setAge, 20, 19, 18);

Der Code ist viel kürzer und die Aussichten sind besser.

Ich möchte einen Wert für das erste Argument festlegen ** Ich habe eine Liste von Studenten **.

Als zweites Argument übergeben wir eine ** Setter-Methodenreferenz **. Diese Methodenreferenz wird als BiConsumer \ <T, U > für die gerade erstellte Methode übergeben und in biConsumer.accept (...) aufgerufen.

Da das dritte und die nachfolgenden Argumente ** variable Argumente ** sind, listen Sie die Werte auf, die Sie festlegen möchten.

Klassenmethodenreferenz und Instanzmethodenreferenz

Ich habe hier eine Frage. Die Setter-Methode sollte normalerweise ** Consumer \ <T > ** verwenden, da sie ein Argument und keinen Rückgabewert enthält. Lassen Sie uns nun kurz erklären, warum wir BiConsumer verwenden, eine funktionale Schnittstelle, die zwei Argumente akzeptiert.

Wenn Sie beispielsweise Conumer \ <T > als Argument verwenden, können Sie das folgende Programm erstellen.

public <T> void setValue(Consumer<T> consumer, T value) {
    consumer.accept(value);
}

Hier erfahren Sie, wie Sie es verwenden.

Student student = new Student();
setValue(student::setCode, "S01001");

Die Unterschiede zur Verwendung von BiConsumer sind wie folgt.

Schnittstelle Methodenreferenz
BiConsumer<T, U> Student::setCode
Consumer<T> student::setCode

Bei Verwendung von BiConsumer wird die Methodenreferenz der Klasse verwendet, und bei Verwendung von Consumer wird ** die Methodenreferenz der Instanz ** verwendet.

Da wir diesmal den Wert für die Instanz in List festlegen möchten, ist es nicht sinnvoll, für jede Instanz in List eine Methodenreferenz zu übergeben. Daher übergebe ich ** Klassenmethodenreferenz ** und Aufrufsetter für jede Instanz in List.

Zusammenfassung

Die folgenden zwei Methoden wurden dieses Mal erstellt.

public <T> List<T> createInstanceList(Supplier<T> supplier, int size) {
    return IntStream.range(0, size)
            .mapToObj(i -> supplier.get())
            .collect(toList());
}

public <T, U> void setValues(List<T> obj, BiConsumer<T, U> biConsumer, U... values) {
    for (int i = 0; i < obj.size(); i++) {
        biConsumer.accept(obj.get(i), values[i]);
    }
}

Normalerweise arbeite ich mit vielen Studenten an der Entwicklung. Da es große Unterschiede in den Fähigkeiten gibt, ist es wichtig, so viele ähnliche Programme wie möglich schreiben zu können und bequeme Methoden zur Verbesserung der Entwicklungseffizienz zu entwickeln.

Sie können schnell einfache und bequeme Methoden erstellen. Je mehr Sie jedoch versuchen, so allgemein wie möglich zu erstellen, desto bequemer werden Sie, wenn Sie die hier vorgestellten generischen und funktionalen Schnittstellen kennen.

Recommended Posts

So erstellen Sie eine bequeme Methode, die Generika und eine funktionale Schnittstelle verwendet
So erstellen Sie eine Methode
So testen Sie eine private Methode und verspotten sie teilweise in Java
So erstellen Sie eine Klasse, die Klasseninformationen erbt
Suchen Sie einen geeigneten Wert für eine Methode und machen Sie sie zu einem ValueObject
Erstellen und Ausführen von Methoden-, Proc- und Methodenklassenobjekten
So erstellen und starten Sie eine Docker-Datei für Payara Micro
So erstellen Sie ein Maven-Repository für 2020
[Swift5] So erstellen Sie einen Begrüßungsbildschirm
[Rails] So erstellen Sie eine Teilvorlage
Eine einfache und bequeme Methode für HashMap
So erstellen Sie einen Validator, der nur die Eingabe in ein Feld zulässt
Server mit Spring Gradle ausführbar So erstellen Sie JAR und WAR
Wie man IGV mit Socket-Kommunikation bedient und wie man einen Ruby Gem mit dieser Methode herstellt
So erstellen Sie überall eine H2-Datenbank
[Rails] So erstellen Sie ein Diagramm mit lazy_high_charts
[Ruby] Verwendung der gsub-Methode und der sub-Methode
So erstellen Sie Pagenationen für das "Kaminari" -Array
So erstellen Sie ein Thema in Liferay 7 / DXP
[1.] So erstellen Sie ein Spring-MVC-Framework-Projekt
So erstellen Sie einfach ein Pulldown mit Rails
[Rails] So erstellen Sie eine Twitter-Freigabeschaltfläche
[Spring-Beispielcode enthalten] So erstellen Sie ein Formular und erhalten mehrere Datensätze
Wie erstelle ich ein Vagrant Plugin, das Sie gelernt haben, als Sie Vagrant-Mutagen gegabelt und veröffentlicht haben?
So erstellen Sie eine Kopf- oder Fußzeile einmal und verwenden sie auf einer anderen Seite
Ich habe versucht, mit Wercker ein Docker-Image zu erstellen und zu veröffentlichen, mit dem GlassFish 5 gestartet wird
So erstellen Sie eine Java-Umgebung in nur 3 Sekunden
So erstellen Sie eine JDBC-URL (Oracle Database, Thin)
So erstellen Sie ein Spring Boot-Projekt in IntelliJ
So erstellen Sie einen Daten-URI (base64) in Java
So verspotten Sie einen Super-Methodenaufruf in PowerMock
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
[Apple-Abonnementangebot] So erstellen Sie eine Signatur für ein Werbeangebot
So erstellen Sie Docker-Compose
Bedingte Java-Verzweigung: Erstellen und Studieren von switch-Anweisungen
So erstellen Sie ein leichtes Container-Image für Java-Apps
So erstellen Sie ein Formular zur Auswahl eines Datums aus dem Kalender
So erstellen Sie ein Platzhalterteil zur Verwendung in der IN-Klausel
Ich möchte eine Methode aufrufen und die Nummer zählen
Erstellen Sie eine Methode, mit der Zeichen von jedem Ort abgerufen werden können
Erstellen Sie eine Methode, um den Steuersatz in Java zurückzugeben
So entwickeln und registrieren Sie eine Sota-App in Java
So erstellen Sie ein Service Builder-Portlet in Liferay 7 / DXP
Wie hinterlasse ich einen Kommentar?
Erstellen Sie eine Java-Methode [Memo] [java11]
So fügen Sie ein Video ein
So erstellen Sie eine JAR-Datei und eine War-Datei mit dem Befehl jar
[Rails 6] So erstellen Sie mit cocoon einen dynamischen Formular-Eingabebildschirm
Wie POST JSON in Java-Methode mit OkHttp3 und Methode mit HttpUrlConnection-
So implementieren Sie einen Job, der die Java-API in JobScheduler verwendet
So erstellen Sie ein neues Gradle + Java + Jar-Projekt in Intellij 2016.03
So stellen Sie eine App bereit, die ein lokales Glas auf Heroku verweist
So laden Sie eine Spring-Upload-Datei und zeigen ihren Inhalt an
So lesen Sie eine Datei und behandeln sie als Standardeingabe
[Bequem zu merken !!!] So konvertieren Sie vom LocalDate-Typ in eine Zeichenfolge und von der Zeichenfolge in den LocalDate-Typ
Speichern der im Textbereich eingegebenen Informationen in einer Variablen in der Methode