Jetzt werden alle sechs Monate neue Versionen von Java veröffentlicht. Von Zeit zu Zeit erscheinen neue Funktionen in ihnen: var in Java 10, Switch-Ausdrücke in Java 14, Datensätze und Muster in Java 16. Natürlich wurden viele Artikel, Blog-Beiträge darüber geschrieben und viele Berichte auf Konferenzen erstellt. Es stellte sich jedoch heraus, dass wir alle ein sehr cooles Sprach-Upgrade verpasst haben, das in Java 14 stattgefunden hat - ein Upgrade auf die reguläre for-Schleife über eine Reihe von Ganzzahlen. Tatsache ist, dass dieses Upgrade nicht in der Sprache, sondern in der virtuellen Maschine durchgeführt wurde, aber die Art und Weise, wie wir in Java programmieren können, erheblich beeinflusst hat.
Erinnern wir uns an die gute alte for-Schleife:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
Diese Syntax hat viele Nachteile. Zunächst wird die Schleifenvariable dreimal erwähnt. Es ist sehr leicht, verwirrt zu werden und die falsche Variable an ein oder zwei Stellen zu erwähnen. Zweitens ist eine solche Variable nicht effektiv endgültig. Es wird nicht explizit an Lambdas oder anonyme Klassen weitergegeben. Aber noch wichtiger: Sie können nicht gegen versehentliches Ändern einer Variablen innerhalb einer Schleife versichert werden. Das Lesen des Codes ist ebenfalls schwierig. Wenn der Körper der Schleife groß ist, ist es nicht so einfach zu sagen, ob er sich auch innerhalb der Schleife ändert, was bedeutet, dass es nicht klar ist. Wir gehen einfach die Zahlen der Reihe nach um oder machen etwas Komplizierteres. Es gibt auch mögliche Fehler, wenn Sie die Richtung der Schleife ändern oder den Rand einschalten müssen. Und es sieht altmodisch aus.
Viele Sprachen haben sich bereits vom schweren Erbe von C entfernt und bieten eine modernere Syntax, bei der Sie einfach einen Zahlenbereich angeben. Nehmen Sie zum Beispiel Kotlin:
for (x in 0 until 10) {
println(x)
}
: , , , . .
Java? , for-each, Java 5. :
/**
*
* @param fromInclusive ()
* @param toExclusive ( )
* @return Iterable, fromInclusive toExclusive.
*/
public static Iterable<Integer> range(int fromInclusive,
int toExclusive) {
return () -> new Iterator<Integer>() {
int cursor = fromInclusive;
public boolean hasNext() { return cursor < toExclusive; }
public Integer next() { return cursor++; }
};
}
rocket science, , . Java:
for (int i : range(0, 10)) { //
System.out.println(i);
}
. final, . . ? - . JMH-:
@Param({"1000"})
private int size;
@Benchmark
public int plainFor() {
int result = 0;
for (int i = 0; i < size; i++) {
result += i * i * i;
}
return result;
}
@Benchmark
public int rangeFor() {
int result = 0;
for (int i : range(0, size)) {
result += i * i * i;
}
return result;
}
, - , JIT- . , JIT . Java 8 :
Benchmark (size) Mode Cnt Score Error Units
BoxedRange.plainFor 1000 avgt 30 622.679 ± 7.286 ns/op
BoxedRange.rangeFor 1000 avgt 30 3591.052 ± 792.159 ns/op
range : 3,5 0,6 . -prof gc
, , rangeFor 13952 , plainFor . , , , 127 . Integer 128-999, 872 16 . , , Iterable, Iterator : (scalar replacement). .
, for , Java . Java:
: Java 14 range ! JIT- , , .
. Java 8 JVM -XX:+UnlockExperimentalVMOptions -XX:+AggressiveUnboxing
. , , :
Java 8-11 0,9 , 12 0,8, 13 . Java 14 , . , . , , .
? - Integer 127. valueOf ( Java 16):
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
, IntegerCache.low IntegerCache.high , . , , : . AggressiveUnboxing JIT- , , . , - :
Field field = Class.forName("java.lang.Integer$IntegerCache").getDeclaredField("cache");
field.setAccessible(true);
Integer[] arr = (Integer[]) field.get(null);
arr[130] = new Integer(1_000_000);
for (int i = 0; i < 10000; i++) {
int res = rangeFor();
if (res != -1094471800) {
System.out.println("oops! " + res + "; i = " + i);
break;
}
}
, , . Java if
. AggressiveUnboxing
oops! 392146832; i = 333
JIT- C2 rangeFor, , , , .
, Java 12 cmp r10d,7fh
, 127 (=0x7f). , Java 13. , , , - . , Java 12 rangeFor 8 , Java 13 16 , plainFor.
, : Java 14, . for (int i : range(0, 10))
Java for (int i = 0; i < 10; i++)
, .
Valhalla. Iterable<int>
, . , range . Iterable<Integer>
.