GirişBu konuyla ilgili aslında tam bir uzlaşma yok. Bazılarına göre bu durum kabul edilebilir.
Taraf 1'in Savunması
Optional method argument olmamalı diyenlerin açıklaması
şöyle. Yani "Never use Optional as a method argument" diyenler. Bunlara Taraf 1 diyelim
Optional is not a replacement for null nor a fancy way to prevent NullPointerException. It is to indicate that the question is unanswerable, like: what is the average age of an empty list of persons.
Optionals should never be passed on, but unboxed by the calling code as soon as possible.
Taraf 1'in açıklaması
şöyle. Yani null değer istemiyorsak
@NonNull kullanarak zaten bunu yakalayabiliriz.
While writing a method it is recommended to annotate the required argument with @NonNull . Since author of the code knows which argument is required and which not . So better to use basic validation and throw exception in case of validation failed.
Bu konuda bir yazı da
şöyle
In Java, there's no way to know whether a variable is null. To be explicit, Java 8 introduced the Optional type. From Java 8 onward, returning an Optional implies the underlying value can be null; returning another type implies it cannot.
However, the developers of Optional designed it for return values only. Nothing is available in the language syntax for methods parameters and return values. To cope with this, a bunch of libraries provide compile-time annotations:
NotNull anotasyonu sağlayan bazı kütüphaneler
şöyle
Taraf 2'nin Savunması
Optional method argument
olabilir diyenlerin açıklaması
şöyle. Bunlara Taraf 2 diyelim.
Passing an Optional result to another method, without any semantic analysis; leaving that to the method, is quite alright.
Optional method argument olmamalı diyenler şöyle kodlar olmamalı
diyorlar.
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Optional Metod Argument İstemiyorsak
Çözüm 1 - Optional Parametreden Kurtulmak İçin Overload metod kullanmakAşağıdaki örneklerde her iki tarafın da haklı olduğu örnekler verdim.
Örnek - Tek parametre null olabiliyorsaEğer Optional kullansaydık şöyle
yapardıkpublic SystemMessage(String title, String content, Optional<Attachment> attachment) {
// assigning field values
}
Taraf 1'e uyarak Optional parametreden kurtulmak için metodumuzu overload ederek şöyle
yapalım. Burada Attachment parametresi null olabiliyor.
public SystemMessage(String title, String content) {
this(title, content, null);
}
public SystemMessage(String title, String content, Attachment attachment) {
// assigning field values
}
Overload edilen metodun birinci halini çağırmak için şöyle
yaparızSystemMessage withoutAttachment = new SystemMessage("title", "content");
Overload edilen metodun ikinci halini çağırmak için şöyle
yaparızAttachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);
Örnek - İki parametre null olabiliyorsaBu örnekte aslında Optional parametre
geçmemenin kodu daha da zorlaştırdığı görülüyor.
Optional kullansaydık şöyle
yapardık.
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Taraf 1'e uyarak Optional parametreden kurtulmak için metodumuzu overload ederek şöyle
yapalım. Burada null olabilecek parametreler için metod overload ediliyor.
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Bu durumda kodu çağırmak için şöyle
yaparız. Görüldüğü gibi kod daha karmaşık hale gelmeye başladı
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
if (p2.isPresent()) {
result = myObject.calculateSomething(p1, p2);
} else {
result = myObject.calculateSomething(p1);
}
} else {
if (p2.isPresent()) {
result = myObject.calculateSomething(p2);
} else {
result = myObject.calculateSomething();
}
}
Çözüm 2 - Optional Parametreden Kurtulmak İçin Metod Çağrısında Optional.orElse KullanmakÖrnek
Metodumuzdaki Optional parametreleri kaldırarak şöyle
yaparız. Metoda null parametre gelecekmiş gibi kabul edip, kontrol etmek gerekir.
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Bu durumda kullanmak için şöyle
yaparız.
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
ÖrnekElimizde şöyle bir kod
olsunpublic void doAction() {
OptionalInt age = getAge();
Optional<Role> role = getRole();
applySettings(name, age, role);
}
Metod imzasında Optional parametre kullanmamaya karar verdiysek şöyle
yaparız. Burada default değerler kullanılıyor.
public void doAction() {
OptionalInt age = getAge();
Optional<Role> role = getRole();
applySettings(name, age.orElse(defaultAge), role.orElse(defaultRole));
}