Dans cet article, basé sur les éléments de l'aperçu des Documents officiels Apple en option, le type ʻOptional de Swift et Java 8 Types ʻCompare Optional
. Bien que le contenu soit un peu rafraîchissant maintenant, je l'ai publié en tant que note personnelle.
Fin de l'article comprend également un tableau de comparaison de chaque notation. Veuillez les regarder tous ensemble.
Les extraits de code de cet article ont été un peu simplifiés, de sorte que certains d'entre eux ne fonctionneront pas même si vous les copiez et collez tels quels. Notez s'il vous plaît.
Swift
Déballez ʻOptinal pour renvoyer le contenu, le cas échéant, ou la valeur par défaut spécifiée dans le cas contraire. Utilisez l'opérateur «??». Vous pouvez également connecter plusieurs types ʻOptional
comme opérandes.
Swift
let wrappedValue: String? = nil
let defaultValue = "default"
let value = wrappedValue ?? defaultValue
print(value)
// "default"
Swift
let wrappedValue: String? = nil
let defaultValue = "default"
let otherWrappedValue: String? = nil
//Tant que l'opérande droit est facultatif??Peut être connecté avec
let value = wrappedValue ?? otherWrappedValue ?? defaultValue
print(value)
// "default"
Java 8
Dans Java 8, ce n'est pas un opérateur mais une méthode appelée ʻorElse, ʻorElseGet
. ʻOrElse transmet la valeur par défaut elle-même, et ʻorElseGet
transmet un objet de typeSupplier <? Etend T>
qui fournit la valeur par défaut. Cependant, les deux méthodes retournent un type encapsulé, donc vous ne pouvez pas connecter les types ** facultatifs avec ʻou Sinon
comme Swift **.
Java
Optional<String> wrappedValue = Optional.empty();
String defaultValue = "default";
String value = wrappedValue.orElse(defaultValue);
System.out.println(value);
// "default"
String otherValue = wrappedValue.orElseGet( () -> defaultValue );
System.out.println(otherValue);
// "default"
Java
Optional<String> otherWrappedValue = Optional.of("other");
//Je ne peux pas faire ça
// String unwrappedValue = wrappedValue.orElse(otherWrappedValue).orElse(defaultValue);
Swift
L'opérateur de jointure Nil de Swift évalue le court-circuit. Par conséquent, l'opérande droit ne sera pas évalué à moins que l'opérande gauche ne soit «nil».
Swift
func hoge() -> String {
print("called")
return "hoge"
}
let value = nil ?? hoge()
print(value)
// "called"
// "hoge"
//Puisqu'il s'agit d'une évaluation de court-circuit, hoge()N'est pas appelé
let value = "non nil" ?? hoge()
print(value)
// "non nil"
Java 8
ʻOu Else Get de Java 8 est aussi une évaluation de court-circuit, mais ** ʻou Else
ne le fait pas **. C'est naturel car la valeur par défaut elle-même est transmise.
Java
public String hoge() {
System.out.println("called");
return "hoge";
}
String value = Optional.<String>empty().orElseGet(this::hoge);
System.out.println(value);
// "called"
// "hoge"
//Puisqu'il s'agit d'une évaluation de court-circuit, hoge()N'est pas appelé
String value = Optional.of("non null").orElseGet(this::hoge);
System.out.println(value);
// "non null"
Java
//orElse n'évalue pas le court-circuit
String value = Optional.of("non null").orElse(hoge());
System.out.println(value);
// "called"
// "non null"
En ce qui concerne une utilisation correcte, si cela coûte de l'argent pour générer la valeur par défaut, il est préférable d'utiliser ʻorElseGet` pour l'évaluation des courts-circuits.
Java
public String fetchValue() {
//Processus chronophage
return result;
}
// △ -Assurez-vous de récupérerValeur()Est appelé, donc au moins cela affecte les performances
String value = wrappedValue.orElse(fetchValue());
// ◯ -Puisqu'il s'agit d'une évaluation de court-circuit, elle ne sera pas appelée s'il y a du contenu
String value = wrappedValue.orElseGet(this::fetchValue);
Java
// △ -S'il y a du contenu, ce sera la génération d'objets inutile
Person person = wrappedPerson.orElse(new Person());
// ◯ -Puisqu'il s'agit d'une évaluation de court-circuit, aucun objet ne sera créé s'il y a du contenu
Person person = wrappedPerson.orElseGet(Person::new);
Swift
Décompresse la valeur avec ou sans contenu. Utilisez l'opérateur «!». S'il est "nil", cela provoquera une erreur d'exécution.
Swift
let number = Int("42")!
print(number)
// 42
Java 8
Java 8 utilise la méthode get
. S'il est «null», une exception non vérifiée «NoSuchElementException» est levée.
renvoie le type ʻOptional <Integer>
pour la commodité de l'explication, mais il est généralement préférable d'utiliser le type ʻOptionalInt` lors de l'encapsulation d'un entier.Java
public Optional<Integer> intFromString(String string) {
try {
return Optional.of(Integer.parseInt(string));
} catch (NumberFormatException ignored) {
return Optional.empty();
}
}
int number = intFromString("42").get();
System.out.println(number);
// 42
Swift
Convertissez la valeur. Utilisez une méthode appelée map
. S'il y a du contenu, la valeur est convertie selon la fermeture de type (Wrapped) -> U
donnée, et si elle est" nulle ", elle est transmise comme" nil ". Par conséquent, il renvoie le type ʻOptional`.
Swift
let intString: String? = "42"
let percentage: String? = intString.map { "\($0)%" }
print(String(describing: percentage))
// Optional("42%")
Si vous voulez retourner un type ʻOptional dans une fermeture, utilisez la méthode
flatMapqui prend une fermeture de type
(Wrapped) -> Optional ` comme argument.
Swift
let intString: String? = "42"
// Int(String)Est Int?rends le
let integer: Int? = intString.flatMap { Int($0) }
print(String(describing: integer))
// Optional(42)
Java 8
Java 8 utilise également les méthodes map
et flatMap
. L'utilisation est la même.
Java
Optional<String> intString = Optional.of("42");
Optional<String> percentage = intString.map( str -> str + "%" );
System.out.println(percentage);
// Optional[42%]
Java
Optional<String> intString = Optional.of("42");
Optional<Integer> integer = intString.flatMap(this::intFromString);
System.out.println(integer);
// Optional[42]
Swift
Je pense que c'est une méthode de déballage sûre. En combinant avec des mots-clés tels que «if» et «guard», il est possible de brancher le processus selon qu'il y a du contenu ou non.
Swift
let wrappedValue: String? = "value"
if let value: String = wrappedValue {
print(value)
} else {
print("no value")
}
// "value"
Swift
let wrappedValue: String? = "value"
guard let value: String = wrappedValue else {
print("no value")
return
}
print(value)
// "value"
Java 8
Dans Java 8, vous pouvez le dérouler en toute sécurité via une méthode appelée ʻifPresent`. Il prend un objet de type «Consumer <? Super T>» comme argument et décrit le traitement lorsqu'il contient un contenu.
Java
Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
System.out.println(str);
});
// "value"
Cependant, il n'y a pas de ** méthode qui puisse décrire le traitement lorsqu'il n'y a pas de contenu **. Par conséquent, si vous voulez décrire les deux processus, vous devez utiliser ʻis Presentpour vérifier l'existence du contenu. Cependant, il est redondant par rapport à Swift car vous devez décrire explicitement le déroulement forcé
get` s'il y a du contenu **.
Java
Optional<String> wrappedValue = Optional.of("value");
if (wrappedValue.isPresent()) {
//Redondant mais doit être explicitement déballé forcé
String value = wrappedValue.get();
System.out.println(value);
} else {
System.out.println("no value");
}
// "value"
Java
Optional<String> wrappedValue = Optional.of("value");
//Décrire dans la clause de la carte
if (!wrappedValue.isPresent()) {
System.out.println("no value");
return;
}
//Redondant mais doit être explicitement déballé forcé
String value = wrappedValue.get();
System.out.println(value);
// "value"
Java
Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
System.out.println(str);
})// .orElse( () -> { //Je ne peux pas faire ça
// System.out.println("no value");
// })
;
De plus, puisque la portée du processus passé à ʻifPresent` est dans l'expression lambda, la méthode appelante ne peut pas être retournée dans ce processus. Par conséquent, si vous souhaitez effectuer un retour anticipé, vous n'avez pas d'autre choix que d'utiliser «is Present».
Java
public boolean foo(Optional<String> wrappedValue) {
//Revenir tôt s'il y a une valeur
if (wrappedValue.isPresent) {
String str = wrappedValue.get();
//Faire quelque chose
return true;
}
//Que faire s'il n'y a pas de valeur
return result;
}
Java
public boolean foo(Optional<String> wrappedValue) {
//Revenir tôt s'il y a une valeur
wrappedValue.ifPresent( str -> {
//Faire quelque chose
// return true; //Cela n'est pas possible car la portée se trouve dans cette expression lambda
});
//Que faire s'il n'y a pas de valeur
return result;
}
Swift
Accédez aux propriétés et aux méthodes uniquement lorsqu'il y a du contenu. Utilisez l'opérateur postfix «?».
Swift
let wrappedValue: String? = "value"
let uppercased: String? = wrappedValue?.uppercased()
print(String(describing: uppercased))
// Optional("VALUE")
Swift
class Hoge {
func hoge() { print("hoge") }
}
let wrappedValue: Hoge? = Hoge()
wrappedValue?.hoge()
// "hoge"
Java 8
Dans Java 8, vous pouvez utiliser la méthode map
introduite précédemment. Si la cible est une méthode, elle peut être écrite de manière concise à l'aide d'une référence de méthode. Cependant, si la cible renvoie un type ʻOptional, vous devez utiliser
flatMap`.
Java
Optional<String> wrappedValue = Optional.of("value");
Optional<String> uppercased = wrappedValue.map(String::toUpperCase);
System.out.println(uppercased);
// Optional[VALUE]
Java
class User {
final String id;
Optional<String> mail = Optional.empty();
User(String id) { this.id = id; }
}
Optional<User> wrappedUser = Optional.of(new User("user1"));
Optional<String> mail = wrappedUser.flatMap( user -> user.mail );
System.out.println(mail);
// Optional.empty
C'est exactement la même notation que lors de l'utilisation de Convert, y compris comment l'utiliser correctement. Java 8 ne fournit aucune notation ou méthode spéciale uniquement pour accéder au champ ou à la méthode de la valeur encapsulée. Pour accéder à une méthode qui ne renvoie pas de valeur, utilisez ʻifPresent` introduit précédemment.
Java
class Hoge {
void hoge() { System.out.println("hoge"); }
}
Optional<Hoge> wrappedValue = Optional.of(new Hoge());
wrappedValue.ifPresent(Hoge::hoge);
// "hoge"
Dans cet article, nous avons comparé les types Java 8 et ʻOptional basés sur la gestion des types ʻOptional
dans Swift. Voici un tableau de comparaison de chaque notation. Surtout en ce qui concerne la reliure optionnelle et le chaînage optionnel, la différence entre les deux est très apparente. La liaison optionnelle Java 8 est un peu plus redondante que Swift car elle ne peut pas être déroulée en même temps que le branchement. De plus, Java 8 ne fournit pas de moyen dédié pour accéder aux valeurs encapsulées, telles que l'opérateur ?
De Swift.
Swift | Java | |
---|---|---|
Opérateur de jointure nul | ?? |
orElse * Évaluation sans court-circuitorElseGet |
Déballage forcé | ! |
get |
conversion | map flatMap |
map flatMap |
Reliure facultative | if let guard let |
ifPresent Ou isPresent Après avoir ramifié àget Déballage forcé avec |
Chaînage facultatif | ? |
Optional Si vous souhaitez renvoyer le typeflatMap Si vous retournez autre chose map S'il ne renvoie pas de valeur ifPresent |
Si vous avez des erreurs, veuillez nous en informer dans les commentaires.
Ici, nous allons introduire les méthodes ʻOptional, ʻor
et ʻifPresentOrElse`, ajoutées dans Java 9. Je ne peux pas parler de Java 8. C'est un bonus complet.
or
Exécute un objet de type Fournisseur <? Etend Facultatif <? Etend T >>
donné lorsqu'il n'y a pas de contenu pour obtenir la valeur par défaut de type ʻOptional. C'est exactement le cas avec l'opérateur de jointure Nil de Swift apportant le type ʻOptional
au bon opérande.
De plus, en raison de l '** évaluation de court-circuit **, l'objet Supplier
donné ne sera pas exécuté tant qu'il a un contenu.
Swift
let wrappedValue: String? = nil
let defaultValue = "default"
let otherWrappedValue: String? = nil
let value = wrappedValue ?? otherWrappedValue ?? defaultValue
print(value)
// "default"
Java
// available Java 9 or later
Optional<String> wrappedValue = Optional.empty();
String defaultValue = "default";
Optional<String> otherWrappedValue = Optional.empty();
//Le type facultatif peut être spécifié comme valeur par défaut dans Java 9 ou version ultérieure
String value = wrappedValue.or( () -> otherWrappedValue ).orElse(defaultValue);
System.out.println(value);
// "default"
ifPresentOrElse
Vous pouvez dériver le processus selon qu'il contient ou non un contenu. S'il y a du contenu, un objet de type Consumer <? Super T>
est exécuté, sinon un objet de type Runnable
est exécuté. Étant donné que vous pouvez également décrire le traitement lorsqu'il est «nul», il est beaucoup plus proche de la liaison optionnelle de Swift par rapport à Java 8.
Swift
let wrappedValue: String? = "value"
if let value = wrappedValue {
print(value)
} else {
print("no value")
}
// "value"
Java
// available Java 9 or later
Optional<String> wrappedValue = Optional.<String>empty();
wrappedValue.ifPresentOrElse( str -> {
System.out.println(str);
}, () -> {
System.out.println("no value");
});
// "no value"
Recommended Posts