Null anahtarında nasıl kullanılır


202
Integer i = ...

switch (i){
    case null:
        doSomething0();
        break;    
    }

Yukarıdaki kodda null anahtar durum ifadesinde kullanamazsınız. Bunu nasıl farklı şekilde yapabilirim? Kullanamıyorum defaultçünkü o zaman başka bir şey yapmak istiyorum.


9
önce anahtar durumu null durumunu kontrol ederse (i == null) {// dosomething}
Nagaraju Badaeni

8
Bu aslında anahtarı kullanışlı hale getirir. Diğer kalıp eşleme dilleri bu şekilde çalışır.
14'te Pirolistik

Yanıtlar:


278

switchJava'daki bir ifade ile bu mümkün değildir . Aşağıdakileri kontrol nulledin switch:

if (i == null) {
    doSomething0();
} else {
    switch (i) {
    case 1:
        // ...
        break;
    }
}

switchİfadelerde rastgele nesneler kullanamazsınız * . Derleyicinin switch (i)nerede iolduğu hakkında şikayet etmemesinin nedeni, IntegerJava'nın Integerbir int. Assylias zaten belirttiğimiz gibi unboxing bir atacağım NullPointerExceptionzaman iolduğu null.

* Java 7 beri kullanabileceğiniz Stringiçinde switchtablolar.

Oracle Docs - Switch hakkında daha fazla bilgi switch(null değişkeni dahil)


16
Enum'ları switch deyimlerinde de kullanabilirsiniz.
joriki

27
Kutusundan dolayı boş bir Integer veya başka bir Wrapper sınıfı kullanamazsınız. Peki ya numaralandırmalar ve ipler? Neden boş olamazlar?
Luan Nico

9
Neden null kısa devre "varsayılan" durumda veya boş bir anahtar için özel bir durumda eşleştirildi dizeleri için uygulanmadı anlamıyorum. Her zaman boş bir kontrol yapmanız gerektiğinden, kodu anlamsızlaştırmak için anahtarları kullanır. Basitleştirmenin anahtarlar için tek kullanım olduğunu söylemiyorum.
Reimius

3
@ Reimius her zaman boş bir kontrol yapmak zorunda değilsiniz. Eğer yöntemlere vermek kod sözleşmeleri saygı varsa, hemen hemen her zaman için yönetebilir değil kodunuzu boş çekler ile darmadağın olması. Gerçi, asserts kullanmak her zaman güzel.
Joffrey

Ayrıca @ LuanNico'nun sorgusuna verilen cevabı bilmek istiyorum. Tipleri ve türleri nullile çalışırken geçerli bir durum olamayacak gibi görünüyor . Belki uygulanması çağrısında dayanır (hatta bu yüzden, neden tedavi olmasa da perde arkasında ? Bir 'sıralı' -1 sahip olarak) ve sürüm kullanılarak şey yapar ve işaretçi karşılaştırma (ya da başka şekilde bir dereferencing gerektirir bir şeye dayanır nesne)? Stringenumenumordinal()nullStringintern()
aroth


40

switch(i)i ise null, bir NullPointerException atar , çünkü Integerbir int. Yani case null, yasadışı olan, hiçbir zaman ulaşılamazdı.

İfadeden önce ben null olmadığını kontrol etmeniz gerekir switch.


23

Java dokümanları açıkça şunları söyledi:

Null anahtar etiketi olarak kullanılmasının yasaklanması, birinin asla yürütülemeyen kod yazmasını engeller. Anahtar ifadesi, kutulu ilkel tür veya enum gibi bir başvuru türündeyse, ifade çalışma zamanında null olarak değerlendirilirse çalışma zamanı hatası oluşur.

Swithch deyimi yürütülmeden önce null değerini doğrulamanız gerekir.

if (i == null)

Bkz . Geçiş Bildirimi

case null: // will never be executed, therefore disallowed.

1
Bağlantınızdaki javadoclar artık "null anahtar etiketi [vb] olarak kullanılmasına karşı yasak" demiyor.
Patrick M


14

Verilen:

public enum PersonType {
    COOL_GUY(1),
    JERK(2);

    private final int typeId;
    private PersonType(int typeId) {
        this.typeId = typeId;
    }

    public final int getTypeId() {
        return typeId;
    }

    public static PersonType findByTypeId(int typeId) {
        for (PersonType type : values()) {
            if (type.typeId == typeId) {
                return type;
            }
        }
        return null;
    }
}

Benim için bu genellikle bir veritabanındaki bir arama tablosu ile uyumludur (yalnızca nadiren güncellenen tablolar için).

Ancak, findByTypeIdbir switch deyiminde (büyük olasılıkla kullanıcı girişinden) kullanmaya çalıştığımda ...

int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
    // Do things only a cool guy would do.
    break;
case JERK:
    // Push back. Don't enable him.
    break;
default:
    // I don't know or care what to do with this mess.
}

... diğerlerinin de belirttiği gibi, bu bir NPE @ ile sonuçlanır switch(personType) {. Uygulamaya başladığım bir çözüm (yani "çözüm") bir UNKNOWN(-1)tür eklemekti .

public enum PersonType {
    UNKNOWN(-1),
    COOL_GUY(1),
    JERK(2);
    ...
    public static PersonType findByTypeId(int id) {
        ...
        return UNKNOWN;
    }
}

Şimdi, önemli olduğu yerde null kontrol yapmak zorunda değilsiniz ve UNKNOWNtürleri idare etmeyi veya etmemeyi seçebilirsiniz . (NOT: -1bir iş senaryosunda olası olmayan bir tanımlayıcıdır, ancak açıkçası kullanım durumunuz için anlamlı bir şey seçin).


2
UNKNOWNBu gördüğüm en iyi çözüm ve nullchecks overcomse.
membersound

5

Yapmak zorundasın

if (i == null) {
   doSomething0();
} else {
   switch (i) {
   }
}

4

Bazı kütüphaneler yerleşik java switchifadesine alternatifler sunmaya çalışır . Vavr bunlardan biri, desen eşleşmesi için genelleştiriyorlar.

Dokümanlarından bir örnek :

String s = Match(i).of(
    Case($(1), "one"),
    Case($(2), "two"),
    Case($(), "?")
);

Herhangi bir yüklem kullanabilirsiniz, ancak birçoğunu kutudan $(null)çıkarırlar ve tamamen yasaldırlar. Bunu alternatiflerden daha zarif bir çözüm buluyorum, ancak bu java8 ve vavr kütüphanesine bağımlılık gerektiriyor ...



2
switch (String.valueOf(value)){
    case "null":
    default: 
}

0

Yapamazsın. Anahtarda temel öğeleri (int, char, kısa, bayt) ve String'i (yalnızca java 7'deki dizeler) kullanabilirsiniz. ilkeller boş olamaz. Değiştirmeden önce ayrı bir durumda
kontrol edin i.


4
Numaralandırmaları da kullanabilirsiniz.
Karu

5
numaralandırma boşsa, aynı soruna sahip olursunuz. BTW, varsayılan bir maddeye sahip olduğu için anahtarın null ile başa

1
@LeonardoKenji Varsayılan yan tümce null ile gerçekten ilgisi yoktur; açtığınız her ne olursa olsun, diğer durumları kontrol etmek için kaydı kaldırılacaktır, bu nedenle varsayılan yan tümce null durumunu ele almaz (bir NullPointerException şansı olmadan önce atılır).
Ben

2
Bence varsayılan fıkra null önceki dava tarafından yakalanmadı olası diğer enum değeri olarak null işlemek anlamına geliyordu
Leo

0

Sadece ANAHTARIN nasıl çalışabileceğini düşünün,

  • ilkellerde otomatik boks için NPE ile başarısız olabileceğini biliyoruz
  • ancak String veya enum için , eşittir çağrıldığı bir LHS değerine ihtiyaç duyan eşittir yöntemini çağırıyor olabilir. Bu nedenle, null üzerinde hiçbir yöntem çağrılamazsa, anahtar null işleyemez.

0

Java 8 ile @tetsuo cevabına dayanarak:

Integer i = ...

switch (Optional.ofNullable(i).orElse(DEFAULT_VALUE)) {
    case DEFAULT_VALUE:
        doDefault();
        break;    
}
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.