In diesem Artikel, basierend auf den Elementen in der Übersicht über Optionale offizielle Apple-Dokumente, Swifts "Optional" -Typ und Java 8 Vergleichen Sie die optionalen Typen. Obwohl der Inhalt jetzt ein wenig erfrischend ist, habe ich ihn als persönliches Memorandum veröffentlicht. Ende des Artikels enthält auch eine Vergleichstabelle für jede Notation. Bitte schauen Sie sie alle zusammen an. Die Schnipsel in diesem Artikel wurden ein wenig vereinfacht, sodass einige davon nicht funktionieren, selbst wenn Sie sie so kopieren und einfügen, wie sie sind. Bitte beachten Sie.
Swift
Packt Optinal
aus, um den Inhalt (falls vorhanden) oder den angegebenen Standardwert anderweitig zurückzugeben. Verwenden Sie den Operator ??
. Sie können auch mehrere optionale Typen als Operanden verbinden.
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
//Solange der richtige Operand optional ist??Kann verbunden werden mit
let value = wrappedValue ?? otherWrappedValue ?? defaultValue
print(value)
// "default"
Java 8
In Java 8 ist es kein Operator, sondern eine Methode namens "orElse", "orElseGet". "orElse" übergibt den Standardwert selbst und "orElseGet" übergibt ein Objekt vom Typ "Supplier <? Extends T>", das den Standardwert bereitstellt. Beide Methoden geben jedoch einen umschlossenen Typ zurück, sodass Sie nicht mehrere optionale Typen wie Swift mit orElse verbinden können.
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");
//Ich kann das nicht machen
// String unwrappedValue = wrappedValue.orElse(otherWrappedValue).orElse(defaultValue);
Swift
Der Nil-Join-Operator von Swift bewertet den Kurzschluss. Daher wird der rechte Operand nur ausgewertet, wenn der linke Operand "Null" ist.
Swift
func hoge() -> String {
print("called")
return "hoge"
}
let value = nil ?? hoge()
print(value)
// "called"
// "hoge"
//Da es sich um eine Kurzschlussauswertung handelt, hoge()Wird nicht genannt
let value = "non nil" ?? hoge()
print(value)
// "non nil"
Java 8
Java 8 oder ElseGet
ist ebenfalls eine Kurzschlussauswertung, ** oder Else
jedoch nicht **. Dies ist natürlich, da der Standardwert selbst übergeben wird.
Java
public String hoge() {
System.out.println("called");
return "hoge";
}
String value = Optional.<String>empty().orElseGet(this::hoge);
System.out.println(value);
// "called"
// "hoge"
//Da es sich um eine Kurzschlussauswertung handelt, hoge()Wird nicht genannt
String value = Optional.of("non null").orElseGet(this::hoge);
System.out.println(value);
// "non null"
Java
//orElse bewertet keinen Kurzschluss
String value = Optional.of("non null").orElse(hoge());
System.out.println(value);
// "called"
// "non null"
In Bezug auf die ordnungsgemäße Verwendung ist es besser, "orElseGet" für die Kurzschlussbewertung zu verwenden, wenn die Generierung des Standardwerts Geld kostet.
Java
public String fetchValue() {
//Zeitaufwändiger Prozess
return result;
}
// △ -Stellen Sie sicher, dass Sie den Wert abrufen()Wird aufgerufen, wirkt sich dies zumindest auf die Leistung aus
String value = wrappedValue.orElse(fetchValue());
// ◯ -Da es sich um eine Kurzschlussauswertung handelt, wird sie nicht aufgerufen, wenn Inhalt vorhanden ist
String value = wrappedValue.orElseGet(this::fetchValue);
Java
// △ -Wenn es Inhalte gibt, ist dies eine nutzlose Objekterzeugung
Person person = wrappedPerson.orElse(new Person());
// ◯ -Da es sich um eine Kurzschlussauswertung handelt, wird kein Objekt erstellt, wenn Inhalt vorhanden ist
Person person = wrappedPerson.orElseGet(Person::new);
Swift
Packt den Wert mit oder ohne Inhalt aus. Verwenden Sie den Operator !
. Wenn es "Null" ist, verursacht es einen Laufzeitfehler.
Swift
let number = Int("42")!
print(number)
// 42
Java 8
Java 8 verwendet die Methode "get". Wenn es "null" ist, wird eine ungeprüfte Ausnahme "NoSuchElementException" ausgelöst.
intFromString
zur Vereinfachung der Erklärung den Typ Optional <Integer>
zurückgibt. Normalerweise ist es jedoch besser, den Typ OptionalInt
zu verwenden, wenn Sie eine Ganzzahl umbrechen.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
Konvertieren Sie den Wert. Verwenden Sie eine Methode namens "map". Wenn Inhalt vorhanden ist, wird der Wert gemäß dem angegebenen Abschluss vom Typ "(Wrapped) -> U" konvertiert, und wenn er "Null" ist, wird er als "Null" ausgegeben. Daher wird der Typ "Optional" zurückgegeben.
Swift
let intString: String? = "42"
let percentage: String? = intString.map { "\($0)%" }
print(String(describing: percentage))
// Optional("42%")
Wenn Sie einen optionalen Typ in einem Abschluss zurückgeben möchten, verwenden Sie die Methode flatMap, die einen Abschluss vom Typ (Wrapped) -> Optional <U>
als Argument verwendet.
Swift
let intString: String? = "42"
// Int(String)Ist Int?Gib es zurück
let integer: Int? = intString.flatMap { Int($0) }
print(String(describing: integer))
// Optional(42)
Java 8
Java 8 verwendet auch die Methoden map
und flatMap
. Die Verwendung ist die gleiche.
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
Ich denke, es ist als sichere Auspackmethode bekannt. Durch die Kombination mit Schlüsselwörtern wie "if" und "guard" ist es möglich, den Prozess zu verzweigen, je nachdem, ob Inhalt vorhanden ist oder nicht.
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
In Java 8 können Sie es sicher über eine Methode namens "ifPresent" entpacken. Es nimmt ein Objekt vom Typ "Consumer <? Super T>" als Argument und beschreibt die Verarbeitung, wenn sich ein Inhalt darin befindet.
Java
Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
System.out.println(str);
});
// "value"
Es gibt jedoch keine ** Methode, die die Verarbeitung beschreiben kann, wenn kein Inhalt vorhanden ist **. Wenn Sie beide Prozesse beschreiben möchten, müssen Sie daher "isPresent" verwenden, um die Existenz des Inhalts zu überprüfen. Es ist jedoch im Vergleich zu Swift redundant, da Sie das erzwungene Entpacken "get" explizit beschreiben müssen, wenn Inhalt ** vorhanden ist.
Java
Optional<String> wrappedValue = Optional.of("value");
if (wrappedValue.isPresent()) {
//Redundant, muss aber explizit zum Auspacken gezwungen werden
String value = wrappedValue.get();
System.out.println(value);
} else {
System.out.println("no value");
}
// "value"
Java
Optional<String> wrappedValue = Optional.of("value");
//Beschreiben Sie in der Kartenklausel
if (!wrappedValue.isPresent()) {
System.out.println("no value");
return;
}
//Redundant, muss aber explizit zum Auspacken gezwungen werden
String value = wrappedValue.get();
System.out.println(value);
// "value"
Java
Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
System.out.println(str);
})// .orElse( () -> { //Ich kann das nicht machen
// System.out.println("no value");
// })
;
Da der an ifPresent
übergebene Umfang des Prozesses innerhalb des Lambda-Ausdrucks liegt, kann die aufrufende Methode innerhalb dieses Prozesses nicht zurückgegeben werden. Wenn Sie also frühzeitig zurückkehren möchten, haben Sie keine andere Wahl, als "isPresent" zu verwenden.
Java
public boolean foo(Optional<String> wrappedValue) {
//Kehre früh zurück, wenn es einen Wert gibt
if (wrappedValue.isPresent) {
String str = wrappedValue.get();
//Etwas tun
return true;
}
//Was tun, wenn kein Wert vorhanden ist?
return result;
}
Java
public boolean foo(Optional<String> wrappedValue) {
//Kehre früh zurück, wenn es einen Wert gibt
wrappedValue.ifPresent( str -> {
//Etwas tun
// return true; //Dies ist nicht möglich, da der Gültigkeitsbereich innerhalb dieses Lambda-Ausdrucks liegt
});
//Was tun, wenn kein Wert vorhanden ist?
return result;
}
Swift
Greifen Sie nur dann auf Eigenschaften und Methoden zu, wenn Inhalt vorhanden ist. Verwenden Sie den Postfix-Operator ?
.
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
In Java 8 können Sie die zuvor eingeführte map
-Methode verwenden. Wenn das Ziel eine Methode ist, kann es mithilfe einer Methodenreferenz präzise geschrieben werden. Wenn das Ziel jedoch einen optionalen Typ zurückgibt, müssen Sie flatMap verwenden.
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
Es ist genau die gleiche Notation wie bei Verwendung von Konvertieren, einschließlich der richtigen Verwendung. Java 8 bietet keine spezielle Notation oder Methode, um nur auf das Feld oder die Methode des umschlossenen Werts zuzugreifen. Verwenden Sie das zuvor eingeführte "ifPresent", um auf Methoden zuzugreifen, die keinen Wert zurückgeben.
Java
class Hoge {
void hoge() { System.out.println("hoge"); }
}
Optional<Hoge> wrappedValue = Optional.of(new Hoge());
wrappedValue.ifPresent(Hoge::hoge);
// "hoge"
In diesem Artikel haben wir Java 8- und "Optional" -Typen basierend auf der Behandlung von "Optional" -Typen in Swift verglichen. Unten finden Sie eine Vergleichstabelle für jede Notation. Besonders wenn es um optionales Binden und optionales Verketten geht, ist der Unterschied zwischen beiden sehr offensichtlich. Die optionale Java 8-Bindung ist etwas redundanter als Swift, da sie nicht gleichzeitig mit der Verzweigung entpackt werden kann. Außerdem bietet Java 8 keine dedizierte Möglichkeit, auf umschlossene Werte zuzugreifen, wie z. B. Swifts ?
Operator.
Swift | Java | |
---|---|---|
Kein Join-Operator | ?? |
orElse * Bewertung des KurzschlussesorElseGet |
Erzwungenes Auspacken | ! |
get |
Umwandlung | map flatMap |
map flatMap |
Optionale Bindung | if let guard let |
ifPresent Oder isPresent Nach der Verzweigung beiget Erzwungenes Auspacken mit |
Optionale Verkettung | ? |
Optional Wenn Sie den Typ zurückgeben möchtenflatMap Wenn Sie etwas anderes zurückgeben map Wenn es keinen Wert zurückgibt ifPresent |
Wenn Sie Fehler haben, teilen Sie uns dies bitte in den Kommentaren mit.
Hier werden wir die "optionalen" Methoden "or" und "ifPresentOrElse" vorstellen, die in Java 9 hinzugefügt wurden. Ich kann nicht über Java 8 sprechen. Es ist ein vollständiger Bonus.
or
Führt ein Objekt vom Typ "Lieferant <? Erweitert Optional <? Erweitert T >>" aus, wenn es leer ist, um den Standardwert vom Typ "Optional" zu erhalten. Dies ist genau der Fall, wenn Swifts Nil-Join-Operator den Typ "Optional" auf den richtigen Operanden bringt. Aufgrund der ** Kurzschlussbewertung ** wird das angegebene "Lieferanten" -Objekt nicht ausgeführt, solange es Inhalt enthält.
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();
//Der optionale Typ kann in Java 9 oder höher als Standardwert angegeben werden
String value = wrappedValue.or( () -> otherWrappedValue ).orElse(defaultValue);
System.out.println(value);
// "default"
ifPresentOrElse
Sie können den Prozess verzweigen, je nachdem, ob er Inhalt enthält oder nicht. Wenn Inhalt vorhanden ist, wird ein Objekt vom Typ "Consumer <? Super T>" ausgeführt, andernfalls wird ein Objekt vom Typ "Runnable" ausgeführt. Da Sie die Verarbeitung auch beschreiben können, wenn sie "null" ist, ist sie der optionalen Bindung von Swift im Vergleich zu Java 8 viel näher.
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