Aynı catch maddesinde birden fazla Java istisnası yakalayabilir miyim?


702

Java, böyle bir şey yapmak istiyorum:

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...onun yerine:

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

Bunu yapmanın bir yolu var mı?

Yanıtlar:


1133

Bu Java 7'den beri mümkün . Çoklu yakalama bloğunun sözdizimi:

try { 
  ...
} catch (IOException | SQLException ex) { 
  ...
}

Ancak, tüm istisnalar aynı sınıf hiyerarşisine aitse, bu temel istisna türünü yakalayabileceğinizi unutmayın.

Ayrıca, ExceptionB, ExceptionA'dan doğrudan veya dolaylı olarak miras alınırsa, ExceptionA ve ExceptionB öğelerini aynı blokta yakalayamayacağınızı unutmayın. Derleyici şikayet edecek:

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

81
TT - bitwise or( |) operatörünü neden yeniden tanımlıyorsunuz ? Neden virgül veya daha benzer bir anlama sahip bir işleç logical or( ||) kullanmıyorsunuz ?
ArtOfWarfare

11
@ArtOfWarfare Belki de jenerikler için çoklu sınırlar sözdizimi oluşturduktan sonra artık önemli olmayacağını düşündüler .
JimmyB

12
XOR işareti (I) OR (||), A | B, A veya B anlamına gelir, ancak her ikisi de A || B, istisnalar için istisnaA veya istisnaB'dir, ancak her ikisini aynı anda değil, A veya B veya her ikisini ifade eder. bu yüzden OR yerine XOR şarkı kullandılar ve 2 istisna koyarsanız istisna
atılırsa

41
@ user1512999 Java, bitsel XOR ^ (düzeltme işareti) ve bitsel VEYA | (boru) docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Lewis Baumstark

6
Çok yakalamalı blokta yakalanan bir istisna türünün en türetilmiş ortak ebeveyne göre değerlendirildiğini belirtmek gerekir
yanpas

104

Tam olarak Java 7'den önce değil, böyle bir şey yapardım:

Java 6 ve öncesi

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}



Java 7

try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException |NoSuchFieldException exc) {
  someCode();
}

11
Java 6 örneğinizin, derleyicinin neyin nereden atılacağını söyleme yeteneğini bozduğunu unutmayın.
MichaelBlume

2
@MichaelBlume Doğru, ki bu kötü değil. İle orijinal istisnayı her zaman alabilirsiniz exc.getCause(). Bir yan not olarak, Robert C. Martin (diğerleri arasında) kontrol edilmeyen istisnaların kullanılmasını önerir (derleyicinin ne tür bir istisnanın oradan atılacağına dair hiçbir fikri yoktur); Bölüm 7: Temiz kod adlı kitabında hata işleme konusuna bakın .
user454322

4
Java 6 örnekte, yani orijinal istisna yeniden atma yerine yeni bir istisna örneğini oluşturarak olmamalı throw excyerine throw new RuntimeException(exc)?
David DeMar

5
Bu, okunabilirlik açısından oldukça kötü bir uygulamadır.
Rajesh J Advani

3
İşlem biraz pahalı, mümkün olduğunca kaçınmak daha iyidir.
Paramesh Korrakuti

23

Java 7 içinde aşağıdakiler gibi birden fazla yakalama maddesi tanımlayabilirsiniz:

catch (IllegalArgumentException | SecurityException e)
{
    ...
}

16

İstisnalar hiyerarşisi varsa, istisnaların tüm alt sınıflarını yakalamak için temel sınıfı kullanabilirsiniz. Dejenere durumda aşağıdaki tüm Java istisnalarını yakalayabilirsiniz :

try {
   ...
} catch (Exception e) {
   someCode();
}

Daha yaygın bir durumda RepositoryException temel sınıf ve PathNotFoundException türetilmiş bir sınıf ise:

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

Yukarıdaki kod, bir tür özel durum işleme için RepositoryException ve PathNotFoundException öğelerini yakalar ve diğer tüm özel durumlar birlikte toplanır. Java 7'den beri, @ OscarRyz'ın cevabına göre:

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

7
BTW catch yan tümceleri sırayla işlenir, bu nedenle alt sınıftan önce bir üst istisna sınıfı koyarsanız, buna asla çağrılmaz örn .: try {...} catch (Exception e) {someCode (); } catch (RepositoryException re) {// hiç ulaşılmadı}
Michael Shopsin

4
Aslında tam olarak ulaşılamadığı için böyle bir kod bile derlenmez.
poligenelubrikantlar

15

Hayır, müşteri başına bir tane.

Tüm durumlarda aynı işlemi yaptığınız sürece, java.lang.Exception gibi bir üst sınıf yakalayabilirsiniz.

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

Ancak bu en iyi uygulama olmayabilir. Bir istisnayı yalnızca gerçekte ele almak için bir stratejiniz olduğunda ve oturum açmak ve yeniden sorgulamak "işlemek" olmadığında yakalamanız gerekir. Düzeltici bir işleminiz yoksa, bunu yöntem imzasına eklemek ve durumu işleyebilecek birine patlatmak daha iyi olur.


20
Java.lang.Exception'ı yakalamakla ilgili bölümü yeniden ifade etmenizi isteyebilir miyim? Bunun bir örnek olduğunun farkındayım, ancak bazı insanların bu cevabı okuyabileceğini ve "ah, tamam, o zaman sadece İstisna'yı yakalayacağım" diyebileceğini düşünüyorum, muhtemelen yapmak istedikleri (veya yapmaları gerekenler) olmadığında.
Rob Hruska

2
Bunu biliyordum, ama yapmak istemiyorum ... Oh, peki, sanırım Java'nın bir sonraki sürümüne kadar 4 yakalama ile sıkıştım ...
froadie

@duffymo: Günlüğe kaydetme ve yeniden bağlama ile ilgili sorun nedir? Kodu karıştırması dışında, onu yakalamamakla eşdeğerdir, değil mi? Genel hata işleme stratejisi perspektifinden bakıldığında. Ne kötü günlüğü ve bir değil yeniden atma.
Frank Osterfeld

5
Günlük tutmayı ve hiçbir şeyi yeniden ele almayı düşünmüyorum. Anlamlı bir şey yapabilecek birine patlamasını tercih ederim. İstisnaların asla kaçmaması gereken son katman (örneğin, bir web uygulamasındaki denetleyiciler), bu durumda hatayı günlüğe alan katman olmalıdır.
duffymo

Bir günlüğün otomatik olarak benim için oluşturulmadığını saçmalayan tek kişi ben miyim? Görünüşe göre hepimiz bir kod parçasının bir istisna atabileceği her seferinde aynı aptal günlük mesajını yazmak zorundayız.
ArtOfWarfare

10

User454322'nin Java 6 (yani Android) üzerindeki cevabına daha temiz (ancak daha az ayrıntılı ve belki de tercih edildiği gibi değil) bir alternatif, tüm Exceptionleri yakalamak ve yeniden atmak olacaktır RuntimeException. Bu, diğer istisna türlerini yığının yukarısında yakalamayı planlıyorsanız işe yaramaz (siz de tekrar atmazsanız), ancak tüm kontrol edilen istisnaları etkili bir şekilde yakalar .

Örneğin:

try {
    // CODE THAT THROWS EXCEPTION
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        // this exception was not expected, so re-throw it
        throw e;
    } else {
        // YOUR CODE FOR ALL CHECKED EXCEPTIONS
    } 
}

Bununla birlikte, ayrıntı için, bir boolean veya başka bir değişken ayarlamak ve buna dayanarak try-catch bloğundan sonra bir kod yürütmek en iyisi olabilir.


1
Bu yaklaşım, derleyicinin bir "catch bloğu" nun erişilip erişilemeyeceğini belirlemesini önler.
the_new_mr

3

Ön 7'de nasıl olur:

  Boolean   caught = true;
  Exception e;
  try {
     ...
     caught = false;
  } catch (TransformerException te) {
     e = te;
  } catch (SocketException se) {
     e = se;
  } catch (IOException ie) {
     e = ie;
  }
  if (caught) {
     someCode(); // You can reference Exception e here.
  }

3
wuold güzel bir çözüm olabilir. Son kontrolünü caughtbir finallybloğa yerleştirmeye ne dersiniz ?
Andrea_86

Bu, orijinal sorudan daha fazla satır gerektirir.
Leandro Glossman

1

Evet. Boru (|) ayırıcısını kullanmanın yolu,

try
{
    .......
}    
catch
{
    catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}

Bu kod stili nedir? Yakalama bloğu bir deneme bloğuna mı?
Sam

1

Kotlin için şimdilik mümkün değil ama eklemeyi düşünüyorlar: Kaynak
Ama şimdilik küçük bir numara:

try {
    // code
} catch(ex:Exception) {
    when(ex) {
        is SomeException,
        is AnotherException -> {
            // handle
        }
        else -> throw ex
    }
}

0

İstisna hiyerarşisinde bir üst sınıf olan istisnayı yakalayın. Bu elbette kötü bir uygulama . Sizin durumunuzda, ortak ana istisna Exception sınıfı olur ve Exception örneği olan herhangi bir istisnayı yakalamak gerçekten kötü bir uygulamadır - NullPointerException gibi istisnalar genellikle programlama hatalarıdır ve genellikle boş değerler kontrol edilerek çözülmelidir.

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.