Java 14 führte eine neue Möglichkeit zur Erstellung von Klassen namens Records ein. In diesem Tutorial werden wir lernen:
- Warum wir Java Records benötigen
- Wie man Records erstellt und verwendet
- Das Überschreiben und Erweitern von Records-Klassen
Empfohlene Lektüre: Java 14 Funktionen
Warum benötigen wir Java Records?
Eine der häufigsten Beschwerden über Java war seine Ausführlichkeit. Wenn Sie eine einfache POJO-Klasse erstellen müssen, ist der folgende Boilerplate-Code erforderlich.
- Private Felder
- Getter- und Setter-Methoden
- Konstruktoren
- hashCode(), equals() und toString()-Methoden.
Diese Ausführlichkeit ist einer der Gründe für das hohe Interesse an Kotlin und Project Lombok.
Tatsächlich führte die reine Frustration beim Schreiben dieser generischen Methoden jedes Mal zu Verkürzungen bei der Erstellung in Java-IDEs wie Eclipse und IntelliJ IDEA.
Hier ist ein Screenshot, der die Eclipse-IDE-Option zum Generieren der zeremoniellen Methoden für eine Klasse zeigt.

Java Records sollen diese Ausführlichkeit entfernen, indem sie eine kompakte Struktur zur Erstellung von POJO-Klassen bereitstellen.
Wie man Java Records erstellt
Java Records ist eine Vorschau-Funktion, die unter JEP 359 entwickelt wurde. Sie benötigen also zwei Dinge, um Records in Ihren Java-Projekten zu erstellen.
- Installiertes JDK 14. Wenn Sie eine IDE verwenden, muss diese auch Java 14 unterstützen. Sowohl Eclipse als auch IntelliJ bieten bereits Unterstützung für Java 14, also sind wir hier gut aufgestellt.
- Aktivieren Sie die Vorschaufunktion: Standardmäßig sind die Vorschaufunktionen deaktiviert. Sie können sie in Eclipse in den Einstellungen des Java-Compilers für das Projekt aktivieren.

Sie können die Java 14 Vorschaufunktionen auch über die Befehlszeile mit der Option --enable-preview -source 14
aktivieren.
Angenommen, Sie möchten eine Employee-Modellklasse erstellen. Es wird ungefähr so aussehen wie der folgende Code.
package com.journaldev.java14;
import java.util.Map;
public class Employee {
private int id;
private String name;
private long salary;
private Map<String, String> addresses;
public Employee(int id, String name, long salary, Map<String, String> addresses) {
super();
this.id = id;
this.name = name;
this.salary = salary;
this.addresses = addresses;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public long getSalary() {
return salary;
}
public Map<String, String> getAddresses() {
return addresses;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addresses == null) ? 0 : addresses.hashCode());
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (salary ^ (salary >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (addresses == null) {
if (other.addresses != null)
return false;
} else if (!addresses.equals(other.addresses))
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (salary != other.salary)
return false;
return true;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", addresses=" + addresses + "]";
}
}
Puh, das sind über 70 Zeilen automatisch generierter Code. Jetzt schauen wir uns an, wie man eine Employee Record-Klasse erstellt, die im Wesentlichen die gleichen Funktionen bietet.
package com.journaldev.java14;
import java.util.Map;
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}
Wow, das kann nicht kürzer werden. Ich liebe bereits Record-Klassen.
Jetzt verwenden wir den javap
-Befehl, um herauszufinden, was hinter den Kulissen passiert, wenn ein Record kompiliert wird.
# javac --enable-preview -source 14 EmpRecord.java
Note: EmpRecord.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
# javap EmpRecord
Compiled from "EmpRecord.java"
public final class EmpRecord extends java.lang.Record {
public EmpRecord(int, java.lang.String, long, java.util.Map<java.lang.String, java.lang.String>);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public int id();
public java.lang.String name();
public long salary();
public java.util.Map<java.lang.String, java.lang.String> addresses();
}
#

# javac —enable–preview –source 14 EmpRecord.java
# javap EmpRecord
Wenn Sie mehr interne Details wünschen, führen Sie den javap-Befehl mit der Option -v aus.
- A Record class is final, so we can’t extend it.
-
# javap -v EmpRecord
-
Wichtige Punkte zu Record-Klassen
Die Record-Klassen erweitern implizit die Klasse
java.lang.Record
. - Alle in der Record-Deklaration angegebenen Felder sind final.
- A single constructor is created with all the fields specified in the record definition.
- Die Record-Felder sind „shallow“ unveränderlich und hängen vom Typ ab. Zum Beispiel können wir das Adressfeld ändern, indem wir darauf zugreifen und dann Aktualisierungen vornehmen.
- Die Record-Klasse stellt automatisch Zugriffsmethoden für die Felder bereit. Der Methodenname entspricht dem Feldnamen, nicht wie bei generischen und herkömmlichen Getter-Methoden.
Die Record-Klasse bietet auch Implementierungen für hashCode(), equals() und toString().
package com.journaldev.java14;
public class RecordTest {
public static void main(String[] args) {
EmpRecord empRecord1 = new EmpRecord(10, "Pankaj", 10000, null);
EmpRecord empRecord2 = new EmpRecord(10, "Pankaj", 10000, null);
Verwendung von Records in Java-Programmen
System.out.println(empRecord1);
Lassen Sie uns ein einfaches Beispiel für die Verwendung unserer EmpRecord-Klasse betrachten.
System.out.println("Name: "+empRecord1.name());
System.out.println("ID: "+empRecord1.id());
// toString()
System.out.println(empRecord1.equals(empRecord2));
// Felder zugreifen
System.out.println(empRecord1 == empRecord2);
}
}
// equals()
EmpRecord[id=10, name=Pankaj, salary=10000, addresses=null]
Name: Pankaj
ID: 10
true
false
// hashCode()
Ausgabe:
Das Record-Objekt funktioniert genauso wie jede Modellklasse, Datenobjekt usw.
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
public EmpRecord {
if (id < 0)
throw new IllegalArgumentException("employee id can't be negative");
if (salary < 0)
throw new IllegalArgumentException("employee salary can't be negative");
}
}
Erweitern des Record-Konstruktors
EmpRecord empRecord1 = new EmpRecord(-10, "Pankaj", 10000, null);
Manchmal möchten wir einige Validierungen oder Protokollierungen in unserem Konstruktor haben. Zum Beispiel sollten Mitarbeiter-ID und Gehalt nicht negativ sein. Der Standardkonstruktor hat diese Validierung nicht. Wir können einen kompakten Konstruktor in der Record-Klasse erstellen. Der Code dieses Konstruktors wird am Anfang des automatisch generierten Konstruktors platziert.
Exception in thread "main" java.lang.IllegalArgumentException: employee id can't be negative
at com.journaldev.java14.EmpRecord.<init>(EmpRecord.java:9)
Wenn wir eine EmpRecord wie im folgenden Code erstellen:
Wir erhalten zur Laufzeit eine Ausnahme wie:
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
public int getAddressCount() {
if (this.addresses != null)
return this.addresses().size();
else
return 0;
}
}
Können Record-Klassen Methoden haben?
Ja, wir können Methoden in Records erstellen.
Aber Records sind dazu gedacht, Daten zu tragen. Es sollte vermieden werden, Hilfsmethoden in einer Record-Klasse zu haben. Zum Beispiel kann die oben genannte Methode in einer Hilfsklasse erstellt werden.
Wenn Sie der Meinung sind, dass es für Ihre Record-Klasse unbedingt eine Methode geben muss, überlegen Sie sorgfältig, ob Sie wirklich eine Record-Klasse benötigen?
Source:
https://www.digitalocean.com/community/tutorials/java-records-class