Cet article est l'article du 12ème jour du Calendrier de l'Avent Kotlin 2019.
Je pense que Kotlin a été dit moderne par rapport à Java. Cependant, le cycle de publication de Java est une fois tous les six mois, et il devient un meilleur langage qu'avant, donc je pense que Java est meilleur lorsque l'on considère la maintenabilité future. Il y a aussi une opinion selon laquelle vous vous demandez peut-être laquelle choisir lors de la sélection d'une langue. Par conséquent, je voudrais comparer les dernières tendances Java avec Kotlin et comparer ce qui est plus moderne.
Les cibles de comparaison sont la dernière version de Kotlin et Java 12 ou des fonctionnalités ultérieures. En ce qui concerne Java, la version 13 a été publiée le 18/09/2019, mais cette fois, j'aimerais comparer certaines fonctionnalités susceptibles d'être incluses dans JDK14 en cours de développement et plus tard. Pour les fonctionnalités avant JDK11, je pense qu'il existe de nombreux autres bons articles, veuillez donc les consulter. Ou il peut être ajouté lorsqu'il y a une marge. </ font>
En ce qui concerne les fonctions ajoutées dans chaque version de JDK, l'article de @ nowokay est assez soigné et facile à comprendre, je voudrais donc y faire référence et le comparer avec Kotlin.
Au fait, Kotlin vient juste de commencer à toucher et je pense qu'il y a certaines parties que je ne comprends pas bien, alors s'il vous plaît faites Masakari.
Référence: Résumé de la nouvelle fonctionnalité Java 12
La version Preview de Switch Expressions est également incluse dans 12, mais comme elle est toujours en cours de correction dans JDK14, je l'expliquerai dans JDK14.
CompactNumberFormat CompactNumberFormat a été introduit dans Java 12, mais Kotlin n'a pas de fonctionnalité similaire.
Java
NumberFormat cnf = NumberFormat.getCompactNumberInstance();
System.out.println(cnf.format(10000)); //10 000
System.out.println(cnf.format(10000_0000)); //Cent millions
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() + "Mille milliards"
}
(number >= 10F.pow(8)) -> {
floor(number / 10F.pow(8)).toLong().toString() + "Milliard"
}
(number >= 10F.pow(4)) -> {
floor(number / 10F.pow(4)).toLong().toString() + "Dix mille"
}
else -> {
number.toString()
}
}
}
println(format(10000)) //10 000
println(format(10000_0000)) //Cent millions
println(format(10000_0000_0000L)) //1 billion
Comme il n'y a que 3 unités, j'ai essayé de le faire un peu de force. Java est meilleur ici, n'est-ce pas? Il semble qu'il y ait peu de possibilités de l'utiliser.
String.indent
Si vous utilisez String.indent, il sera affiché avec l'argument spécifié en retrait.
Java
String s = "Kotlin";
System.out.println(s);
System.out.println(s.indent(2));
// Kotlin
// Kotlin
Dans le cas de Kotlin, utilisez String.prependIndent et indentez avec le caractère spécifié. Cette fois, j'ai mis 2 caractères vides, donc 2 caractères seront en retrait.
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
}
Dans Kotlin, vous pouvez l'écrire de la même manière que String.transform en utilisant la fonction let.
@ rmakiyama et @ anatawa12 m'ont appris à écrire String.transform dans Kotlin! Merci beaucoup. </ font>
Collectors.teeing
Cela semble également difficile à réaliser avec une ligne avec Kotlin. J'ai préparé une fonction à la place et je l'ai réalisé.
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
C'est une API pour vérifier si le contenu du fichier est différent.
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));
}
//Si les fichiers sont les mêmes
// file is same
//Si les fichiers sont différents
// file is diffarent
// row:24
Kotlin ne semble pas avoir d'API similaire. Puisqu'il est difficile d'écrire le processus, je vais l'omettre ici.
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 obtient une erreur de compilation lors de l'utilisation de n.isEmpty ()
.
La sécurité nulle est bonne après tout.
En Java, si vous utilisez ʻisEmpty () pour une variable Null, NPE la sortira. Vous pouvez également compiler en utilisant ʻOptional <String> n = null;
et NPE se produira.
Je me demande si Java pourra effectuer des vérifications Null et Empty en même temps sans utiliser de bibliothèque.
Référence: https://openjdk.java.net/projects/jdk/13/
Les expressions de commutation sont susceptibles de changer un peu plus par rapport au JDK 13, je les comparerai donc plus tard.
Text Blocks
https://openjdk.java.net/jeps/368 Cela changera probablement un peu plus, mais je ne pense pas que cela changera beaucoup.
Java
String s = """
ultra soul
OCEAN
""";
System.out.println(s);
// ultra soul
// OCEAN
Kotlin
val s = """
ultra soul
OCEAN
"""
print(s)
// ultra soul
// OCEAN
C'est presque la même chose pour Java et Kotlin.
Eh bien, il n'est pas encore officiellement publié, mais comparons Kotlin à ce qui est en cours de développement.
Référence: Changements de syntaxe Java envisagés par Amber
Records(JEP 359)
Records prépare automatiquement du code tel que hashCode
ʻequals`` toString`, qui est redondant dans les beans Java.
C'est très simple et agréable.
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
Et Kotlin a une classe de données.
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
L'enregistrement semble faire référence à la classe de cas de Scala, à la classe de données de Kotlin, aux types d'enregistrement de C #, etc.
Sealed Types(JEP 360)
Les types scellés sont utilisés pour limiter l'héritage de classe Ceci est pratique à utiliser comme énumération.
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" }
}
Je ne comprends pas beaucoup le code Java ici, mais j'écrirai une image. (Je me demande si j'ai vu un exemple d'utilisation de scellé / enregistrement avec commutateur quelque part, mais je n'ai pas encore trouvé de problème, donc si j'en trouve un, je vais coller l'URL détaillée)
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";
//Pas besoin de déclaration par défaut car scellé sait que les seules options sont Demio et Vezel
// default -> throw new IllegalStateException("Error");
};
Kotlin est déjà disponible dans l'expression when.
Kotlin
// sealed
sealed class HondaCar
class Demio: HondaCar()
class Vezel: HondaCar()
// use
val hondaName = when(hondaCar) {
is Demio -> "Demio"
is Vezel -> "Vezel"
//Aucune valeur par défaut requise
}
println(hondaName)
À propos, si vous n'utilisez pas de scellé avec Kotlin, la valeur par défaut (else) est requise.
Erreur Kotlin
// interface
interface NissanCar
class Leaf: NissanCar
class Juke: NissanCar
// use
val nissanCar: NissanCar = Leaf()
val nissanName = when(nissanCar) {
is Leaf -> "Leaf"
is Juke -> "Juke"
//Puisqu'il n'y a pas d'autre, l'erreur suivante est sortie
// 'when' expression must be exhaustingstive, add necssary 'else' branch
}
println(nissanName)
Switch Expressions (JEP 361)
https://openjdk.java.net/jeps/361 À l'origine, je pensais que le commutateur Java était difficile à utiliser, mais il a été envisagé depuis JDK12 (JEP 325), et il semble que diverses améliorations aient été apportées. Je veux juste le comparer avec Kotlin, donc je ne décrirai que les parties qui changent de manière significative.
Java
//à l'origine
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
}
//Après amélioration
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);
}
Plusieurs Kotlins peuvent être répertoriés en même temps.
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)
}
Comme mentionné dans Types scellés, il semble que le résultat de switch puisse être utilisé comme expression et stocké dans une variable. Actuellement, lors de l'utilisation de switch dans une boucle telle qu'une instruction for, il semble que le mouvement de pause et continue soit ajusté.
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 prend également en charge la pause et la poursuite du commutateur(C'est une logique inutile)
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)
Après avoir vérifié le type avec instanceof, le type est fixe, donc Pattern Matching for instanceof
peut être utilisé en le stockant dans une variable telle quelle.
Java
//jusqu'à maintenant
if (o instanceof String) {
//Vous ne pouvez pas utiliser o directement comme type de chaîne
// System.out.println(o.length());
//Il est nécessaire de le convertir une fois en type String, puis de l'utiliser
String s = (String)o;
System.out.println(s.length()); // 27
}
//à partir de maintenant
Object o = "Pattern Match of instanceof";
//Peut être stocké dans une variable en même temps que instanceof
if (o instanceof String s) {
System.out.println(s.length()); // 27
}
//Il semble que le commutateur sera également disponible.(OpenJDK 14 Early-Toujours dans 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 peut être utilisé tel quel sans le stocker dans une variable.
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
Tout d'abord, j'ai trouvé incroyable que Java ait autant évolué.
Auparavant, Kotlin était le meilleur. Je pense que Java était une image décevante, mais j'ai l'impression que Java a également adopté des langages modernes comme Kotlin vers JDK17, et la différence est en train de disparaître. Et j'ai été surpris par Kotlin, qui a déjà adopté une telle nouvelle syntaxe Java.
Du point de vue de la comparaison des langages entre Java et Kotlin, Kotlin a toujours des avantages tels que la sécurité NULL et l'écriture facile des types de fonctions, et à partir de septembre 2021, lorsque le prochain LTS, JDK17, sera publié, lequel Je me suis demandé si je pouvais le choisir.
J'écrirai à Kotlin pour le nouveau projet que je vais faire, donc j'aimerais écrire un article séparé sur ce qui m'intéressait tout en m'en occupant à l'avenir.
C'est le reflet que la couleur de Java est devenue plus forte même s'il s'agit d'une publicité de Kotlin.
De plus, je suis désolé que ce soit devenu une expression selon laquelle d'autres personnes réutilisent le contenu déjà dans l'article. Pour la comparaison entre Kotlin et le nouveau Java, il y avait beaucoup de contenu dont j'ai inévitablement souffert même s'il y avait peu d'informations, alors pardonnez-moi.
J'ai réfléchi en écrivant, mais il semble préférable de comparer également JDK9 à JDK11. Nous vous répondrons lorsque vous pourrez vous le permettre.
Kotlin ne l'a pas touché dans les affaires pour le moment, donc je pense qu'il y a certaines parties que je ne comprends pas, alors j'aimerais le corriger progressivement à mesure que ma compréhension s'approfondit.
Résumé des nouvelles fonctionnalités de Java 12 Changements de syntaxe Java envisagés par Amber
https://openjdk.java.net/projects/jdk/13/ https://openjdk.java.net/projects/amber/
Recommended Posts