Dieser Artikel ist der 12. Tagesartikel von Kotlin Adventskalender 2019.
Ich denke, Kotlin soll im Vergleich zu Java modern sein. Der Release-Zyklus von Java findet jedoch alle sechs Monate statt und wird zu einer besseren Sprache als zuvor. Ist Java also nicht besser, wenn man die zukünftige Wartbarkeit berücksichtigt? Es gibt auch eine Meinung, dass Sie sich fragen, welche Sie bei der Auswahl einer Sprache wählen sollen. Daher möchte ich die neuesten Java-Trends mit Kotlin vergleichen und vergleichen, welche moderner sind.
Die Vergleichsziele sind die neueste Version der Funktionen von Kotlin und Java 12 oder höher. In Bezug auf Java wurde Version 13 am 18. September 2019 veröffentlicht, aber dieses Mal möchte ich einige Funktionen vergleichen, die wahrscheinlich in JDK 14 und später in der Entwicklung sind. Für Funktionen vor JDK11 gibt es meiner Meinung nach viele andere gute Artikel. Bitte beziehen Sie sich darauf. Oder es kann hinzugefügt werden, wenn ein Rand vorhanden ist. </ font>
In Bezug auf die Funktionen, die in jeder Version von JDK hinzugefügt wurden, ist der Artikel von @ nowokay ziemlich ordentlich und leicht zu verstehen, daher möchte ich darauf verweisen und ihn mit Kotlin vergleichen.
Übrigens hat Kotlin gerade erst angefangen, sich zu berühren, und ich denke, es gibt einige Teile, die ich nicht gut verstehe, also bitte Masakari.
Referenz: Zusammenfassung der neuen Java 12-Funktionen
Die Vorschau-Version von Switch Expressions ist ebenfalls in 12 enthalten. Da sie jedoch noch in JDK14 behoben wird, werde ich sie in JDK14 erläutern.
CompactNumberFormat CompactNumberFormat wurde in Java 12 eingeführt, Kotlin verfügt jedoch nicht über eine ähnliche Funktion.
Java
NumberFormat cnf = NumberFormat.getCompactNumberInstance();
System.out.println(cnf.format(10000)); //10 000
System.out.println(cnf.format(10000_0000)); //Ein hundert Millionen
System.out.println(cnf.format(10000_0000_0000L)); //1 Billion
}
Kotlin
fun format(number: Long): String {
return when {
(number >= 10F.pow(12)) -> {
floor(number / 10F.pow(12)).toLong().toString() + "Billion"
}
(number >= 10F.pow(8)) -> {
floor(number / 10F.pow(8)).toLong().toString() + "Milliarde"
}
(number >= 10F.pow(4)) -> {
floor(number / 10F.pow(4)).toLong().toString() + "Zehntausend"
}
else -> {
number.toString()
}
}
}
println(format(10000)) //10 000
println(format(10000_0000)) //Ein hundert Millionen
println(format(10000_0000_0000L)) //1 Billion
Da es nur 3 Einheiten gibt, habe ich versucht, es ein wenig gewaltsam zu machen. Java ist hier besser, nicht wahr? Es scheint, dass es nur wenige Möglichkeiten gibt, es zu nutzen.
String.indent
Wenn Sie String.indent verwenden, wird es mit dem angegebenen eingerückten Argument angezeigt.
Java
String s = "Kotlin";
System.out.println(s);
System.out.println(s.indent(2));
// Kotlin
// Kotlin
Verwenden Sie im Fall von Kotlin String.prependIndent und rücken Sie mit dem darin angegebenen Zeichen ein. Dieses Mal habe ich 2 leere Zeichen eingefügt, sodass 2 Zeichen eingerückt werden.
Kotlin
val s = "Kotlin"
println(s)
println(s.prependIndent(" "))
// Kotlin
// Kotlin
String.transform
Java
var addresses = Map.of("Mike", "Fukuoka", "John", "Tokyo");
var population = Map.of("Tokyo", 30000000, "Fukuoka", 2000000);
var name = "Mike";
System.out.println(name.transform(addresses::get).transform(population::get)); // 2000000
Kotlin
fun main() {
val addresses = mapOf("Mike" to "Fukuoka", "John" to "Tokyo")
val population = mapOf("Tokyo" to 30000000, "Fukuoka" to 2000000)
val name = "Mike"
println(name.let(addresses::get)?.let(population::get)) // 2000000
}
In Kotlin können Sie es auf die gleiche Weise wie String.transform schreiben, indem Sie die Funktion let verwenden.
@ rmakiyama und @ anatawa12 haben mir beigebracht, wie man String.transform in Kotlin schreibt! Vielen Dank. </ font>
Collectors.teeing
Dies scheint auch mit einer Linie mit Kotlin schwer zu erreichen zu sein. Ich habe stattdessen eine Funktion vorbereitet und realisiert.
Java
Map.Entry<String, Long> map = Stream.of("aaa", "", "bbb", "ccc").
filter(Predicate.not(String::isEmpty)).
collect(Collectors.teeing(
Collectors.joining(","),
Collectors.counting(),
Map::entry));
System.out.println(map); // aaa,bbb,ccc=3
Kotlin
fun listToMap(list: List<String>): Map<String, Int> {
return mutableMapOf(list.joinToString(",") to list.count())
}
val list = mutableListOf("aaa", "", "bbb", "ccc")
.filter { !it.isBlank() }
.toList()
println(listToMap(list)) // {aaa,bbb,ccc=3}
Files.mismatch
Es ist eine API, um zu überprüfen, ob der Inhalt der Datei unterschiedlich ist.
Java
Path filePath1 = Path.of("./com/example/jdk12/FilesMismatchFile1.txt");
Path filePath2 = Path.of("./com/example/jdk12/FilesMismatchFile2.txt");
long mismatchRow = Files.mismatch(filePath1, filePath2);
if (mismatchRow == -1) {
System.out.println("file is same");
} else {
System.out.println("file is diffarent¥nrow:" + String.valueOf(mismatchRow));
}
//Wenn die Dateien gleich sind
// file is same
//Wenn die Dateien unterschiedlich sind
// file is diffarent
// row:24
Kotlin scheint keine ähnliche API zu haben. Da es schwierig ist, den Prozess zu schreiben, werde ich ihn hier weglassen.
String.isEmpty
Java
String s = "";
String n = null;
if (s.isEmpty()) {
System.out.println("s is Empty");
}
if (n.isEmpty()) {
System.out.println("n is Empty");
}
// s is Empty
// Exception in thread "main" java.lang.NullPointerException
// at com.example.jdk12.StringIsEmpty.main(StringIsEmpty.java:10)
Kotlin
val s = "";
val n: String? = null;
if (s.isEmpty()) {
println("s is Empty")
}
if (n.isNullOrEmpty()) {
println("n is Null")
}
// s is Empty
// n is Null
Kotlin erhält einen Kompilierungsfehler, wenn n.isEmpty ()
verwendet wird.
Nullsicherheit ist schließlich gut.
Wenn Sie in Java "isEmpty ()" für eine Null-Variable verwenden, gibt NPE diese aus.
Sie können auch mit Optional <String> n = null;
kompilieren, und NPE wird auftreten.
Ich frage mich, ob Java in der Lage sein wird, gleichzeitig Null- und Leerprüfungen durchzuführen, ohne eine Bibliothek zu verwenden.
Referenz: https://openjdk.java.net/projects/jdk/13/
Switch-Ausdrücke ändern sich wahrscheinlich etwas mehr von JDK 13, daher werde ich sie später vergleichen.
Text Blocks
https://openjdk.java.net/jeps/368 Es wird sich wahrscheinlich ein bisschen mehr ändern, aber ich denke nicht, dass es sich viel ändern wird.
Java
String s = """
ultra soul
OCEAN
""";
System.out.println(s);
// ultra soul
// OCEAN
Kotlin
val s = """
ultra soul
OCEAN
"""
print(s)
// ultra soul
// OCEAN
Für Java und Kotlin ist es fast dasselbe.
Nun, es wurde nicht offiziell von hier veröffentlicht, aber vergleichen wir Kotlin mit den Inhalten, die sich in der Entwicklung befinden.
Referenz: Änderungen der Java-Syntax werden von Amber berücksichtigt
Records(JEP 359)
Datensätze bereiten automatisch Code wie hashCode`` gleich`` toString
vor, der in Java-Beans redundant ist.
Es ist sehr einfach und schön.
Java
record Point(int x, int y) {}
Point point1 = new Point(5, 10);
Point point2 = new Point(5, 10);
System.out.println(point1.x()); // 5
System.out.println(point1); // Point[x=5, y=10]
System.out.println(point1.equals(point2)); // true
Und Kotlin hat eine Datenklasse.
Kotlin
data class Point(val x: Int, val y: Int)
val point1 = Point(5, 10)
val point2 = Point(5, 10)
println(point1.x) // 5
println(point1) // Point(x=5, y=10)
println(point1.equals(point2)) // true
Der Datensatz scheint sich auf die Fallklasse von Scala, die Datenklasse von Kotlin, die Datensatztypen von C # usw. zu beziehen.
Sealed Types(JEP 360)
Versiegelte Typen werden verwendet, um die Klassenvererbung zu begrenzen Dies ist bequem als Aufzählung zu verwenden.
Java
sealed interface HondaCar {};
public class Demio implements HondaCar {
public String getName() {
return "Demio";
}
}
public class Vezel implements HondaCar {
public String getName() {
return "Vezel";
}
}
Kotlin
sealed class HondaCar
class Demio: HondaCar() {
fun getName():String { return "Demio" }
}
class Vezel: HondaCar() {
fun getName():String { return "Vezel" }
}
Ich verstehe den Java-Code hier nicht sehr gut, aber ich werde ein Bild schreiben. (Ich frage mich, ob ich irgendwo ein Beispiel für die Verwendung von Sealed / Record mit Switch gesehen habe, aber ich habe noch keine Probleme gefunden. Wenn ich eines finde, füge ich die detaillierte URL ein.)
Java
// sealed
sealed interface HondaCar permits Demio, Vezel {}
record Demio() implements HondaCar {}
record Vezel() implements HondaCar {}
// use
int price = switch(hondaCar) {
case Demio(int price) -> "Demio";
case Vezel(int price) -> "Vezel";
//Keine Notwendigkeit für eine Standardanweisung, da versiegelt weiß, dass die einzigen Optionen Demio und Vezel sind
// default -> throw new IllegalStateException("Error");
};
Kotlin ist bereits im when-Ausdruck verfügbar.
Kotlin
// sealed
sealed class HondaCar
class Demio: HondaCar()
class Vezel: HondaCar()
// use
val hondaName = when(hondaCar) {
is Demio -> "Demio"
is Vezel -> "Vezel"
//Kein Standard erforderlich
}
println(hondaName)
Übrigens, wenn Sie nicht mit Kotlin versiegelt verwenden, ist Standard (sonst) erforderlich.
Kotlin-Fehler
// interface
interface NissanCar
class Leaf: NissanCar
class Juke: NissanCar
// use
val nissanCar: NissanCar = Leaf()
val nissanName = when(nissanCar) {
is Leaf -> "Leaf"
is Juke -> "Juke"
//Da es sonst nichts gibt, wird der folgende Fehler ausgegeben
// 'when' expression must be exhaustingstive, add necssary 'else' branch
}
println(nissanName)
Switch Expressions (JEP 361)
https://openjdk.java.net/jeps/361 Ursprünglich dachte ich, dass der Java-Switch schwierig zu verwenden ist, aber er wurde seit JDK12 (JEP 325) in Betracht gezogen, und es scheint, dass verschiedene Verbesserungen vorgenommen wurden. Ich möchte es nur mit Kotlin vergleichen, deshalb werde ich nur die Teile beschreiben, die sich signifikant ändern.
Java
//ursprünglich
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
}
//Nach der Verbesserung
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
Es können mehrere Kotlins gleichzeitig aufgelistet werden.
Kotlin
when (day) {
Day.MONDAY, Day.FRIDAY, Day.SUNDAY -> println(6)
Day.TUESDAY -> println(7)
Day.THURSDAY, Day.SATURDAY -> println(8)
Day.WEDNESDAY -> println(9)
}
Wie unter Versiegelte Typen erwähnt, scheint das Ergebnis des Wechsels als Ausdruck verwendet und in einer Variablen gespeichert zu werden. Derzeit scheint bei Verwendung von switch in einer Schleife wie einer for-Anweisung die Bewegung von break and continue angepasst zu werden.
Java
int j = switch (day) {
case MONDAY -> 0;
case TUESDAY -> 1;
default -> {
int k = day.toString().length();
int result = f(k);
yield result;
}
};
Kotlin
val j = when (day) {
is Monday -> 0;
is Tuesday -> 1;
else -> {
val k = day.toString().length
k
}
}
//Kotlin unterstützt auch break and continue im Switch(Es ist nutzlose Logik)
loop@ for (i in 1..100) {
when (day) {
is Monday -> j = 0;
is Tuesday -> j = 1;
else -> {
j = day.toString().length
break@loop
}
}
}
Pattern Matching for instanceof (JEP 305)
Nach dem Überprüfen des Typs mit instanceof ist der Typ festgelegt, sodass "Pattern Matching for instanceof" verwendet werden kann, indem er in einer Variablen gespeichert wird, wie er ist.
Java
//bis jetzt
if (o instanceof String) {
//Sie können o nicht direkt als String-Typ verwenden
// System.out.println(o.length());
//Es ist notwendig, es einmal in den String-Typ umzuwandeln und dann zu verwenden
String s = (String)o;
System.out.println(s.length()); // 27
}
//von jetzt an
Object o = "Pattern Match of instanceof";
//Kann gleichzeitig mit instanceof in einer Variablen gespeichert werden
if (o instanceof String s) {
System.out.println(s.length()); // 27
}
//Es scheint, dass der Schalter auch verfügbar sein wird.(OpenJDK 14 Early-Noch in Access Build 25)
// https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
switch (o) {
case Integer i -> System.out.println(i);
case String s -> System.out.println(s.length());
}
Kotlin kann unverändert verwendet werden, ohne es in einer Variablen zu speichern.
Kotlin
val o: Any = "Pattern Match of instanceof"
if (o is String) {
println(o.length) // 27
}
when(o) {
is Int -> println("Int")
is String -> {
val s:String = o
println(s)
}
}
// 27
Zunächst fand ich es erstaunlich, dass sich Java so stark weiterentwickelt hat.
Zuvor war Kotlin der Beste. Ich denke, Java war ein enttäuschendes Bild, aber ich habe den Eindruck, dass Java auch moderne Sprachen wie Kotlin in Richtung JDK17 übernommen hat und der Unterschied verschwindet. Und ich war überrascht von Kotlin, das bereits eine so neue Java-Syntax übernommen hat.
Unter dem Gesichtspunkt des Sprachvergleichs zwischen Java und Kotlin bietet Kotlin immer noch Vorteile wie NULL-Sicherheit und einfaches Schreiben von Funktionstypen, und ab September 2021, wenn das nächste LTS, JDK17, veröffentlicht wird, welches Ich fragte mich, ob ich es wählen könnte.
Ich werde in Kotlin für das neue Projekt schreiben, das ich machen werde, daher möchte ich einen separaten Artikel darüber schreiben, woran ich interessiert war, während ich mich in Zukunft tatsächlich damit beschäftige.
Es ist ein Spiegelbild, dass die Farbe von Java stärker geworden ist, obwohl es eine Werbung von Kotlin ist.
Es tut mir auch leid, dass der Ausdruck so geworden ist, dass andere Personen den bereits im Artikel enthaltenen Inhalt wiederverwenden. Für den Vergleich zwischen Kotlin und dem neuen Java gab es viele Inhalte, die ich unweigerlich unter dem Mangel an Informationen leiden würde. Bitte verzeihen Sie mir.
Ich dachte beim Schreiben, aber es scheint besser, JDK9 auch mit JDK11 zu vergleichen. Wir werden antworten, wenn Sie es sich leisten können.
Kotlin hat es im Moment im Geschäft nicht angerührt, daher denke ich, dass es einige Teile gibt, die ich nicht verstehe. Deshalb möchte ich es schrittweise korrigieren, wenn sich mein Verständnis vertieft.
Zusammenfassung der neuen Funktionen von Java 12 Änderungen der Java-Syntax werden von Amber berücksichtigt
https://openjdk.java.net/projects/jdk/13/ https://openjdk.java.net/projects/amber/
Recommended Posts