İsteğe Bağlı Kullanımları


271

Java 8'i 6 aydan daha uzun bir süredir kullandıktan sonra, yeni API değişikliklerinden oldukça memnunum. Hala emin olmadığım bir alan ne zaman kullanılacağıdır Optional. Bir şey olabileceği her yerde kullanmak istemek arasında sallanıyorum nullve hiçbir yerde.

Kullanabileceğim çok fazla durum var gibi görünüyor ve faydalar (okunabilirlik / boş güvenlik) eklediğinden veya yalnızca ek yüke neden olup olmadığından asla emin değilim.

Bu yüzden birkaç örneğim var ve topluluğun Optionalfaydalı olup olmadığı konusundaki düşünceleriyle ilgileniyorum .

1 - Genel bir yöntem olarak, yöntemin geri dönebileceği tür null:

public Optional<Foo> findFoo(String id);

2 - Param olabileceği zaman bir yöntem parametresi olarak null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 - Fasulyenin isteğe bağlı bir üyesi olarak:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 - Giriş Collections:

Genel olarak düşünmüyorum:

List<Optional<Foo>>

bir şey ekler - özellikle değerlerin filter()kaldırılması nullvb. için kullanılabilir, ancak Optionalkoleksiyonlar için iyi bir kullanım alanı var mı?

Kaçırdığım vakalar var mı?


2
Yararlı bulduğum bir örnek, örneğin bir ikame haritanız varsa. Mesela Map<Character, String>. Hiçbir ikamesi varsa bunu kullanabilirsiniz: Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)). Ayrıca İsteğe bağlı Guava çalındı ​​ve çok daha güzel bir sözdizimi olduğunu unutmayın:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
fge

3
Ayrıca, koleksiyonlarda boş değerlere izin vermeyen koleksiyonlar var! İsteğe bağlı buraya fatura uyuyor. Ve .filter(Optional::absent)"boş değerler"
çıkarabilirsiniz

2
@fge Tüm adalette, İsteğe bağlı kavramının aslında FP'den kaynaklandığını düşünüyorum .
VH-NZZ

2
@fge ile daha iyi ifade edilmiyor getOrDefault()mu?
Jim Garrison

Yanıtlar:


206

Ana noktası Optional, bir dönüş değeri olmadığını belirtmek için bir değer döndüren bir işlev için bir araç sağlamaktır. Bu tartışmaya bakın . Bu, arayan kişinin akıcı yöntem çağrıları zincirine devam etmesini sağlar.

Bu , OP'nin sorusundaki 1. numaralı kullanım örneğiyle en yakından eşleşir . Rağmen bir değere yokluğu daha kesin bir formüldür boş gibi bir şey bu yana IntStream.findFirstreturn null asla.

2 numaralı kullanım örneği için , isteğe bağlı bir argümanı bir yönteme geçirerek, bu işe yarayabilir, ancak oldukça sakar. Dize alan ve ardından isteğe bağlı ikinci bir dize alan bir yönteminiz olduğunu varsayalım. A'nın Optionalikinci argüman olarak kabul edilmesi, aşağıdaki gibi kodlarla sonuçlanır:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Null değerini kabul etmek bile daha güzel:

foo("bar", "baz");
foo("bar", null);

Muhtemelen en iyisi, tek bir dize argümanını kabul eden ve ikincisi için bir varsayılan sağlayan aşırı yüklenmiş bir yönteme sahip olmaktır:

foo("bar", "baz");
foo("bar");

Bunun sınırlamaları vardır, ancak yukarıdakilerden herhangi birinden çok daha hoştur.

Kullanım örnekleri 3. ve 4. bir olan, Optionalbir veri yapısı bir sınıfı alanına ya da, API kötüye olarak kabul edilir. İlk olarak, Optionalyukarıda belirtildiği gibi ana tasarım hedefine aykırıdır . İkincisi, herhangi bir değer katmıyor.

Birinde bir değerin yokluğu ile başa çıkmanın üç yolu vardır Optional: ikame değer sağlamak, ikame değer sağlamak için bir işlev çağırmak veya bir istisna atmak. Bir alana depolarsanız, bunu başlatma veya atama zamanında yaparsınız. Bir listeye değer ekliyorsanız, OP'nin belirttiği gibi, sadece değeri eklememek, böylece mevcut olmayan değerleri "düzleştirmek" için ek seçeneğiniz vardır.

Eminim birileri gerçekten Optionalbir alanda veya koleksiyonda saklamak istedikleri bazı vakalarla karşılaşabilir , ancak genel olarak bunu yapmaktan kaçınmak en iyisidir.


46
# 3'e katılmıyorum. OptionalBir değerin varlığı ya da yokluğu üzerine yapılacaklar ya da yapılmayacak bir alan olarak sahip olunması yararlı olabilir .
glglgl

15
if(foo == null)Dahili olarak yapmanın neden sadece alanı depolamaktan daha iyi olacağını anlamıyorum optional. Ve getOptionalFoo()dahili olarak aramanın neden sadece alanı bir olarak depolamaktan daha iyi olduğunu anlamıyorum Optional. Bir alan olabilir Ayrıca, nullve bir alan olamaz nullbunları yaparak derleyiciye o iletişim kuramaz neden Optionalya da değil Optional.
mogronalol

27
@StuartMarks, tüm Optional<>uzmanlardan duyduğumda beni şaşırtan şeylerden biri : " Optional<>bir alanda saklamayın ". Gerçekten bu öneriyi anlamaya çalışıyorum. Bir düğümün bir üst öğeye sahip olabileceği veya olmayabileceği bir DOM ağacı düşünün. Geri Node.getParent()dönecek kullanım durumunda görünüyor Optional<Node>. Gerçekten nullher seferinde a'yı saklayıp sonucu sarmam bekleniyor mu? Neden? Kodumun çirkin görünmesi dışında bu ekstra verimsizlik beni ne satın alıyor?
Garret Wilson

7
@GarretWilson Öte yandan, varsayalım Optional<Node> getParent() { return Optional.ofNullable(parent); }. Bu pahalı görünüyor çünkü Optionalher seferinde ayırıyor ! Ancak arayan hemen onu açarsa, nesne son derece kısa ömürlüdür ve asla alan alanından yükseltilmez. Hatta JIT'in kaçış analizi ile bile ortadan kaldırılabilir. Sonuç olarak, her zamanki gibi "bağlıdır", ancak Optionalpotansiyel olarak bellek kullanımı, bellek kullanımını şişirir ve veri yapısı geçişini yavaşlatır. Ve nihayet bence kodları karıştırıyor, ama bu bir zevk meselesi.
Stuart Marks

6
@GarretWilson Bunun için bir blog yazdınız mı? Bununla ilgilenirim :)
akhil_mittal

78

Oyuna geç kaldım ama buna değer için 2 Cent'imi eklemek istiyorum. Stuart Marks'ın cevabı ile iyi özetlenen tasarım hedefineOptional karşı çıkıyorlar , ancak yine de geçerliliklerinden ikna oldum (açıkçası).

Her Yerde İsteğe Bağlı Kullan

Genel olarak

Kullanımı hakkındaOptional bir blog yazısı yazdım ama temelde bu geliyor:

  • Mümkün olan her yerde seçeneklerden kaçınmak için sınıflarınızı tasarlayın
  • kalan tüm durumlarda, varsayılan değer Optional,null
  • muhtemelen aşağıdakiler için istisnalar yapın:
    • yerel değişkenler
    • değerleri ve bağımsız değişkenleri özel yöntemlere döndürme
    • performans kritik kod blokları (tahmin yok, bir profil oluşturucu kullanın)

İlk iki istisna, içindeki sargı ve paketten çıkarma referanslarının algılanan yükünü azaltabilir Optional. Bir sıfırın hiçbir zaman yasal olarak bir örnekten diğerine geçemeyeceği şekilde seçilirler.

Bunun neredeyse hiç Optionals kadar kötü koleksiyonlara izin vermeyeceğini unutmayın null. Sadece yapma. ;)

Sorularınızla ilgili

  1. Evet.
  2. Aşırı yükleme bir seçenek değilse, evet.
  3. Diğer yaklaşımlar (alt sınıf, dekorasyon, ...) seçenek yoksa, evet.
  4. Lütfen hayır!

Avantajları

Bunu yapmak null, onları yok etmese de, kod tabanınızdaki s'nin varlığını azaltır . Ama asıl mesele bu bile değil. Başka önemli avantajlar da var:

Niyeti Açıklar

Kullanmak Optional, değişkenin isteğe bağlı olduğunu açıkça ifade eder. Kodunuzun veya API'nızın tüketicisinin herhangi bir okuyucusu, orada hiçbir şey olmayabileceği ve değere erişmeden önce bir kontrolün gerekli olduğu gerçeğiyle kafa üzerinde dövülecektir.

Belirsizliği Kaldırır

OptionalBir nulloluşumun anlamı olmadan belirsizdir. Bir durumun yasal bir temsili (bkz. Map.get) Veya eksik veya başarısız başlatma gibi bir uygulama hatası olabilir.

Bu, sürekli kullanımı ile önemli ölçüde değişir Optional. Burada, zaten nullbir hatanın varlığı anlamına gelir. (Çünkü değerin eksik olmasına izin verilmiş Optionalolsaydı , bir kullanılmış olurdu.) Bunun anlamı, boş bir işaretçi istisnasının hata ayıklamasını çok daha kolay hale getirir null.

Daha Fazla Boş Kontrol

Artık hiçbir şey yapılamayacağına göre null, bu her yerde uygulanabilir. Ek açıklamalarla, iddialarla veya açık denetimlerle, bu argümanın veya bu dönüş türünün boş olup olmadığını asla düşünmek zorunda kalmazsınız. Yapamaz!

Dezavantajları

Tabii ki, gümüş kurşun yok ...

Verim

Değerlerin (özellikle ilkellerin) fazladan bir örneğe kaydırılması performansı düşürebilir. Sıkı döngülerde bu farkedilebilir veya daha da kötüleşebilir.

Derleyicinin kısa ömürlü ömürleri için ekstra referansı atlatabileceğini unutmayın Optional. Java 10'da değer türleri cezayı daha da azaltabilir veya kaldırabilir.

serileştirme

Optionalserileştirilemez ancak geçici bir çözüm çok karmaşık değildir.

Değişmezlik

Java'daki genel türlerin değişmezliği nedeniyle, gerçek değer türü genel tür bağımsız değişkenine itildiğinde belirli işlemler hantal hale gelir. Burada bir örnek verilmiştir (bkz. "Parametrik polimorfizm") .


Başka bir dezavantaj (veya sınırlama), Oracle'ın bu kısıtlamayı kasıtlı olarak dayatmasına rağmen, İsteğe bağlı (xxx) örneklerini sıralayamamanızdır. Bu sınıfların yalnızca belirli durumlarda kullanılması gereken yerlerde mevcut olma bilgisine ve geliştiricinin doğru şeyi yapacağını varsayarak şüpheliyim. Bir problemi çözmek diğerine neden olabilir. Belki İsteğe Bağlı (xxx) sınıflarını "istenmeyen" yollarla (örneğin yöntem parametreleri, koleksiyonlarda, kurucularda vb. Gibi) kullanırken geliştiriciye yardımcı olması için derleyici uyarıları olmalıdır.
skomisa

Yaklaşık 4, koleksiyonlarda opsiyonel: Bazen opsiyonelleri Lists cinsinden saklamak faydalı olabilir . Bu, belirli bir öğenin belirli bir dizinde yer almasının önemli olduğu, ancak öğenin mevcut olup olmadığı durumudur. Bu açıkça bir List<Optional<T>>tür tarafından iletilir . Öte yandan, bazı nesnelerin üye olduğu nesnelerin sadece bazı koleksiyonları önemliyse, nokta yoktur.
Lii

3
Bence # 2. durum hala çok tartışmalı. Bir Optionalyönteme geçirilen varlık olabilir null. Peki ne kazandın? Şimdi iki kontrolünüz var. Bkz. Stackoverflow.com/a/31923042/650176
David V

2
@DavidV verdiğim avantajlar listesine bakın - hepsi de bu dava için geçerlidir. Ayrıca, her şeyi kabul ederseniz Optional(bunu argüman olarak iletmek istiyorsanız durum böyle olmalıdır) nullasla yasal bir değer değildir. Bu nedenle null, açık bir parametreyle bir yöntem çağırmak açıkça bir hatadır.
Nicolai

28

Şahsen ben kullanmayı tercih intellij en Kod Muayene Aracı kullanımına @NotNullve @Nullablebu büyük ölçüde derleme zamanı (bazı çalışma zamanı kontrolleri olabilir) Bu kod okunabilirliği ve çalışma zamanı performansı açısından daha düşük yüke sahiptir olduğu gibi çek. İsteğe bağlı kullanımı kadar titiz değildir, ancak bu titizlik eksikliği, uygun birim testleri ile desteklenmelidir.

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

Bu Java 5 ile çalışır ve değerleri sarmaya ve açmaya gerek yoktur. (veya sarmalayıcı nesneleri oluştur)


7
Uhm, bu IDEA ek açıklamaları mı? Ben JSR 305'in @Nonnullşahsen tercih ediyorum - FindBugs ile çalışır;)
fge

@fge Bu konuda standartların eksikliği var, ancak araçların genellikle yapılandırılabilir olduğuna ve bununla bitmek zorunda olmadığınıza inanıyorum@Nonnull @NotNull etc
Peter Lawrey

4
Evet bu doğru; IDEA (13.x) üç farklı seçenek sunuyor ... Meh, her zaman JSR 305
anywa

3
Bunun eski olduğunu biliyorum, ancak ek açıklamalar ve araçlar hakkındaki tartışma stackoverflow.com/questions/35892063/… için bir bağlantıyı hak ediyor - btw özellikle Java 8 davasına hitap ediyor.
Stephan Herrmann

25

Guava İsteğe bağlı ve wiki sayfası oldukça iyi koyar düşünüyorum:

Null adının verilmesinden kaynaklanan okunabilirlikteki artışın yanı sıra, İsteğe Bağlı'nın en büyük avantajı aptal geçirmezliğidir. Programınızın hiç derlenmesini istemiyorsanız sizi aktif olmayan durum hakkında aktif olarak düşünmeye zorlar, çünkü isteğe bağlı olarak aktif olarak paketini açmanız ve bu durumu ele almanız gerekir. Null, işleri unutmayı rahatsız edici bir şekilde kolaylaştırır ve FindBugs yardımcı olsa da, konuyu neredeyse ele aldığını düşünmüyoruz.

Bu, özellikle "mevcut" veya mevcut olmayan değerleri döndürürken önemlidir. Siz (ve diğerleri), other.method (a, b) öğesinin, other.method'u uygularken a'nın boş olabileceğini unutabileceğinizden boş bir değer döndüğünü unutmanız çok daha olasıdır. İsteğe Bağlı Döndürme, arayanların bu durumu unutmasını imkansız hale getirir, çünkü kodlarının derlenmesi için nesneyi kendi başlarına açmak zorunda kalırlar. - (Kaynak: Guava Wiki - Boş kullanma ve kaçınma - Neyin anlamı var? )

OptionalBazı ek yükler ekler, ancak bence onun açık avantajı, bir nesnenin bulunmayabileceğini açıkça belirtmek ve programcıların durumu ele almasını zorunlu kılmaktır . Birisinin sevgili != nullçeki unutmasını önler .

2 örnek alarak, yazmak için çok daha açık kod olduğunu düşünüyorum:

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

göre

if(soundcard != null){
  System.out.println(soundcard);
}

Benim için, Optionalses kartı bulunmadığı gerçeği daha iyi yakalar.

Puanlarınız hakkında benim 2 ¢:

  1. public Optional<Foo> findFoo(String id);- Bunun hakkında emin değilim. Belki bir döneceğini Result<Foo>olabilir ki boş veya içerirler Foo. Benzer bir kavram, ama gerçekten bir değil Optional.
  2. public Foo doSomething(String id, Optional<Bar> barOptional);- Peter Lawrey'nin cevabında olduğu gibi @Nullable ve bir findbugs kontrolünü tercih ederim - ayrıca bu tartışmaya da bakın .
  3. Kitap örneğiniz - İsteğe bağlı olarak dahili olarak kullanıp kullanamayacağımdan emin değilim, bu karmaşıklığa bağlı olabilir. Bir kitabın "API" Optional<Index> getIndex()için, kitabın bir dizini olmayabilir açıkça belirtmek için bir.
  4. Koleksiyonlarda kullanmam, koleksiyonlarda boş değerlere izin vermem

Genel olarak, etrafta dolaşmayı en aza indirmeye çalışırdım null. (Bir kere yandığında ...) Bence uygun soyutlamaları bulmaya ve diğer programcılara belirli bir dönüş değerinin gerçekte neyi temsil ettiğini göstermeye değer.


15
Sen yazardın soundcard.ifPresent(System.out::println). Arama isPresentanlamsal olarak kontrol etmekle aynıdır null.
daha iyi bir oliver

Sorun şu ki, İsteğe bağlı türlere sahip şeyler hala boş olabilir. Yani tamamen güvenli olabilmek için böyle bir şey yapmalısınız if(soundcard != null && soundcard.isPresent()). Isteğe bağlı ve aynı zamanda null dönebilir bir api yapmak olsa da hiç kimse umarım bir şeydir.
Simon Baumgardt-Wellander

"Programınızın hiç derlenmesini istemiyorsanız sizi aktif olmayan durum hakkında aktif olarak düşünmeye zorlar, çünkü isteğe bağlı olarak aktif olarak paketini açmanız ve bu durumu ele almanız gerekir." Bunu nasıl zorladığından emin değilim, ancak Java'da çok fazla çalışmıyorum. Java'nın sizi paketten çıkarmaya zorlamak için ne yaptığını açıklayabilir misiniz ve sadece derlemek için! İsPresent durumunu kontrol edin?
ezmek

15

Gönderen Oracle öğretici :

İsteğe Bağlı'nın amacı, kod tabanınızdaki her bir boş referansın yerini almak değil, yalnızca bir yöntemin imzasını okuyarak kullanıcıların isteğe bağlı bir değer bekleyip beklemeyeceklerini söyleyebilecekleri daha iyi API'ler tasarlamaya yardımcı olmaktır. Buna ek olarak, İsteğe bağlı olarak, bir değerin yokluğu ile başa çıkmak için bir İsteğe Bağlı'yı aktif olarak açmaya zorlar; sonuç olarak, kodunuzu istenmeyen boş gösterici istisnalarına karşı korursunuz.


3
Sadece yöntemin dönüş kısmı için API'lar, değil mi? Opsiyonel tip silme nedeniyle parametre olarak kullanılmamalıdır? bazen bir nulllable parametreden dönüştürülmüş veya bir boş null yapıcı parametresinden başlangıç ​​olarak bir alan olarak dönüştürülmüş bir yöntemde isteğe bağlı olarak kullanın ... hala null olarak bırakmak daha yararlı olup olmadığını anlamaya çalışıyorum - kimse herhangi bir düşünce var mı?
ycomp

@ycomp Bu veya bu sorudaki vakalar hakkında oldukça fazla bilgi bulabilirsiniz . Bu soruların cevapları, sorulandan çok daha fazlasını anlatır ve diğer vakaları kapsar. Daha fazla bilgi için, daha fazla göz atın veya kendi sorunuzu sorun, çünkü burada çok fazla dikkat çekmeyeceksiniz. ; )
ctomek

8

1 - Genel bir yöntem olarak, yöntem null değerini döndüğünde dönüş türü:

İşte olan iyi bir makale gösterileri USECASE 1. yararlılığını söyledi. İşte bu kod

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

buna dönüştü

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

ilgili alıcı yöntemlerinin dönüş değeri olarak İsteğe bağlı'yı kullanarak .


2

İşte ilginç bir kullanım (inanıyorum) ... Testler.

Projelerimden birini ağır bir şekilde test etmek istiyorum ve bu nedenle iddialarda bulunuyorum; sadece doğrulamam gereken şeyler var ve bilmediğim diğerleri var.

Bu nedenle, iddia etmek ve doğrulamak için bir iddia kullanmak için bir şeyler inşa ediyorum, şöyle:

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

NodeAssert sınıfında şunu yaparım:

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

Yani iddia sadece etiketi kontrol etmek istersem gerçekten tetiklenir!


2

Optionalclass null, daha iyi bir alternatif kullanmaktan kaçınmanızı sağlar :

  • Bu, geliştiriciyi yakalanmamışlardan kaçınmak için varlığını kontrol etmeye teşvik eder NullPointerException.

  • API, daha iyi belgelenir, çünkü mevcut olmayan değerlerin nerede beklendiğini görmek mümkündür.

Optionalnesne ile daha fazla çalışma için uygun API sağlar isPresent():; get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().

Buna ek olarak, birçok çerçeve bu veri türünü aktif olarak kullanır ve API'larından döndürür.


2

Java'da, işlevsel programlamaya bağımlı olmadıkça bunları kullanmayın.

Onlar yöntem argümanları olarak yer yok (Birisi size bir gün boş bir isteğe bağlı değil, boş bir isteğe bağlı geçecek prommess).

Dönüş değerleri için mantıklıdır, ancak müşteri sınıfını davranış oluşturma zincirini germeye devam etmeye davet ederler.

FP ve zincirlerin java gibi zorunlu bir dilde çok az yeri vardır, çünkü sadece okumayı değil, hata ayıklamayı çok zorlaştırır. Çizgiye adım attığınızda, programın durumunu veya amacını bilemezsiniz; Bunu anlamak için adım atmanız gerekir (adım filtrelerine rağmen çoğu zaman sizin olmayan kod çerçevelerine ve derin yığın çerçevelerine) ve eklediğiniz kod / lambdada durabildiğinden emin olmak için çok fazla kesme noktası eklemeniz gerekir, if / else / call önemsiz hatlarını yürümek yerine.

Fonksiyonel programlama istiyorsanız, java'dan başka bir şey seçin ve umarım hata ayıklamak için araçlara sahipsiniz.


1

İsteğe bağlı olarak potansiyel olarak boş değerler döndüren yöntemlerin genel bir yerine geçeceğini düşünmüyorum.

Temel fikir şudur: Bir değerin olmaması, gelecekte potansiyel olarak mevcut olduğu anlamına gelmez. FindById (-1) ve findById (67) arasındaki farktır.

Arayan için Opsiyonellerin ana bilgileri, verilen değere güvenemeyebileceği, ancak bir süre için mevcut olabileceğidir. Belki tekrar kaybolacak ve daha sonra bir kez daha geri gelecektir. Bu bir açma / kapama düğmesi gibidir. Işığı açmak veya kapatmak için "seçeneğiniz" vardır. Ancak açılacak bir ışığınız yoksa seçeneğiniz yoktur.

Bu yüzden daha önce null değerinin geri döndürüldüğü her yerde Opsiyonelleri tanıtmak çok dağınık buluyorum. Yine de null kullanacağım, ancak sadece bir ağacın kökü, tembel başlatma ve açık bulma yöntemleri gibi kısıtlı alanlarda kullanacağım.


0

Görünüşe Optionalİsteğe yazın T gibi temel bir tür ise sadece yararlıdır int, long, charvb "gerçek" sınıfları için, bir kullanabilirsiniz olarak benim için bir anlam ifade etmiyor nullzaten değerini.

Bence buradan (ya da benzer bir dil konseptinden) alındı.

Nullable<T>

C # 'da bu Nullable<T>değer türlerini sarmak için uzun zaman önce tanıtılmıştır.


2
Bu Guava bir ripoff olan Optionalgerçeği de
FGE

2
@fge Tamam ama bu C # (2005, MS.NET 2.0) 'da mevcut olduğunda, Guava yoktu bence. Ve ... C # bunu nereden aldýđýný kim bilebilir.
peter.petrov

3
@fge "Guava'nın Opsiyonel Ripoff" u koymak için komik bir yol, çünkü Guava çocuklar tartışmalara katıldı, deneyimlerini sağladı ve genellikle lehine java.util.Optional.
Stuart Marks

6
@fge Şüphesiz Java'nın API'leri Guava'lardan güçlü bir şekilde etkilendi. Çalmak gibi görünen "ripoff" ile ilgili sorun alıyorum. Guava adamlar katkıda Java 8. değerli fikirler bir sürü
Stuart Marks

6
Konuyu kaçırıyorsun. Boş döndürmek yerine isteğe bağlı kullanılmalıdır. Potansiyel olarak NullPointerException özel durumundan daha güvenli. Bakınız: oracle.com/technetwork/articles/java/…
Kilizo

0

A , Yineleyici tasarım modelinin değiştirilemez bir örneğiyle benzer anlamlara sahiptir :Optional

  • bir nesneye atıfta bulunabilir veya olmayabilir (tarafından verildiği gibi isPresent())
  • get()bir nesneye atıfta bulunursa, kayıttan çıkartılabilir (kullanılarak )
  • ancak sekanstaki bir sonraki konuma ilerletilemez ( next()yöntemi yoktur ).

Bu nedenle Optional, daha önce bir Java kullanmayı düşünmüş olabileceğiniz bir bağlamda döndürmeyi veya aktarmayı düşünün Iterator.


-1

Java SE 8, java.util adında yeni bir sınıf sunar.

Boş değerde boş bir İsteğe bağlı veya İsteğe bağlı oluşturabilirsiniz.

Optional<String> emptyOptional = Optional.empty(); 

Ve burada null değeri olmayan bir İsteğe bağlı:

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

Bir Değer Varsa Bir Şey Yapın

Artık İsteğe bağlı bir nesneye sahip olduğunuza göre, değerlerin varlığı veya yokluğu ile açık bir şekilde ilgilenmek için mevcut yöntemlere erişebilirsiniz. Boş bir kontrol yapmayı hatırlamak yerine, aşağıdaki gibi:

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

İfPresent () yöntemini aşağıdaki gibi kullanabilirsiniz:

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}

Bu kopya macunu ucuz itibar kazanmayı amaçladı, ancak OP'nin sorularıyla ilgili değil
stinger
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.