15. Januar 2021

Java Records 2

Digital Transformation & Development
Software Development & Architecture
Java Records_2

In der letzten Folge haben wir angeschaut was Java Records sind und wie man diese selbst erweitern kann. Diesmal wollen wir uns weitere Beispiele anschauen.

Validierung

Java Records definieren automatisch einen Konstruktor, aber man kann diesen überschreiben. Dies kann z.B. nützlich sein um die Werte eines Records zu validieren. Dazu ein kleines Beispiel. Wir definieren ein Record Range mit unterer und oberer Grenze lo und hi. Wir möchten bei der Erstellung prüfen, ob lo wirklich kleiner ist als hi und im Fehlerfall eine Exception werfen. Dazu überschreiben wir den Konstruktor. Gemacht wird dies durch einen Codeblock mit dem Namen des Records und den {} Klammern. Wir prüfen die Werte lo und hi und werfen gegebenenfalls eine Exception. Dabei können wir gerade die toString() Methode benutzen, die der Record ja automatisch schon hat.

record Range(int lo, int hi) { 
    public Range {
        if (lo > hi) 
            throw new IllegalArgumentException(this.toString());        
    }
}
Range r1 = new Range(1, 2);
System.out.println(r1);

$ Range[lo=1, hi=2]
Range r2 = new Range(2, 1);
System.out.println(r2);

$ java.lang.IllegalArgumentException: Range[lo=0, hi=0]
	at Range.<init>(#17:5)
	at .(#21:1)

Mehrere Return Werte

Dass eine Methode mehrere Werte zurückgeben soll war ja unser Ausgangspunkt in der letzten Folge der Java Perlen. Wir haben die Klasse Pair definiert und dann umgeschrieben in einen Record. Hier nun ein weiteres Beispiel zu diesem Thema, welches mehrere Features der neueren Java Versionen nutzt. Wir möchten in einer Methode aus einer Input Liste (bzw. Stream) von Integers das min und max zurückgeben.  Java 8 bietet alles was dazu nötig ist. Man kann dazu min /max von den Streams und den Comparator von Integer nutzen. Dann die beiden Werte in einen Record packen … und fertig.

Optional <Integer> min = Stream
  .of(1, 8, 2, 5)
  .min(Integer::compareTo);

Optional <Integer> max = Stream
  .of(1, 8, 2, 5)
  .max(Integer::compareTo);
Optional <Integer> min = Stream
    .of(1, 8, 2, 5)
    .collect(Collectors.minBy(Integer::compareTo));

Optional <Integer> max = Stream
    .of(1, 8, 2, 5)
    .collect(Collectors.maxBy(Integer::compareTo));