Java yöntemi bildiriminde atımlar ne zaman kullanılır?


82

Bu yüzden Java'da istisna işleme konusunda iyi bir temel anlayışa sahip olduğumu düşündüm, ancak son zamanlarda kafamı karıştıran ve şüphe uyandıran bazı kodlar okudum. Burada ele almak istediğim ana şüphem, bir kişinin aşağıdaki gibi bir Java yöntemi bildiriminde ne zaman atması gerektiğidir:

    public void method() throws SomeException
    {
         // method body here
    }

Bazı benzer mesajları okuyunca ben toplamak atar o bildirinin bir tür olarak kullanılır SomeException yönteminin uygulanması sırasında atılan edilebilir.

Benim kafa karışıklığım şuna benzer bir koddan kaynaklanıyor:

     public void method() throws IOException
     {
          try
          {
               BufferedReader br = new BufferedReader(new FileReader("file.txt"));
          }
          catch(IOException e)
          {
               System.out.println(e.getMessage());
          }
     }

Bu örnekte atış kullanmak istemeniz için herhangi bir sebep var mı ? Görünüşe göre, bir IOException gibi bir şeyin temel istisna işlemesini yapıyorsanız, sadece dene / yakala bloğuna ihtiyacınız olacak ve bu kadar.

Yanıtlar:


79

Bir istisna türü yakalıyorsanız, onu yeniden atmadıkça atmanıza gerek yoktur. Gönderdiğiniz örnekte, geliştiricinin ikisini birden değil, birini veya diğerini yapmış olması gerekir.

Tipik olarak, istisna dışında hiçbir şey yapmayacaksanız, onu yakalamamalısınız.

Yapabileceğiniz en tehlikeli şey, bir istisna yakalamak ve onunla hiçbir şey yapmamaktır.

İstisnaları atmanın ne zaman uygun olduğuna dair iyi bir tartışma burada

Ne zaman bir istisna yapılmalı?


2
Kontrol edilmeyen istisnalar da yöntem imzasında bir 'atar' ile bildirilmeli mi, yoksa kontrol edilen istisnalar için sadece 'atışlar' kullanılması bir uygulama mı?
Cody

Bu cevap, sorunun ana yönüne doğrudan hitap etmemektedir: throwsAnahtar kelimenin kullanımı .
Brent Bradburn

@hvgotcodes Bir istisna yakalayıp hiçbir şey yapmazsam ne olur?
Manoj

@manoj, önemli bilgiler kaybolduğu için bir şeyleri kırma ve çözememe riskiyle karşı karşıya kalırsınız. Bir istisna yakalamanın ve hiçbir şey yapmamanın uygun olduğu zamanlar (java olması gerekmez) vardır, ancak bunlar belgelenmelidir. Örneğin, javascript'te bir tarayıcıya bağlı olarak mevcut olmayabilecek işlevselliği çalıştırmayı deneyebilirsiniz. Bu mutlaka dikkat edilmesi gereken bir hata değildir.
hvgotcodes

22

Yöntem, denetlenen bir istisna atarsa, bir yönteme yalnızca throws deyimi eklemeniz gerekir. Yöntem bir çalışma zamanı istisnası atarsa, buna gerek yoktur.

Kontrol edilen ve kontrol edilmeyen istisnalar hakkında bazı arka plan için buraya bakın: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Yöntem istisnayı yakalar ve onunla dahili olarak ilgilenirse (ikinci örneğinizde olduğu gibi), bir throws cümlesi eklemeye gerek yoktur.


9

Baktığınız kod ideal değil. Şunlardan birini yapmalısınız:

  1. İstisnayı yakalayın ve halledin; bu durumda throwsgereksizdir.

  2. Kaldır try/catch; bu durumda İstisna bir çağırma yöntemi tarafından ele alınacaktır.

  3. İstisnayı yakalayın, muhtemelen bir eylem gerçekleştirin ve ardından istisnayı yeniden atın (yalnızca mesajı değil)


2

Haklısın, bu örnekte throwsgereksiz. Bir önceki uygulamadan orada bırakılmış olabilir - belki de istisna, catch bloğunda yakalanmak yerine başlangıçta atılmıştır.


2

Gönderdiğiniz kod yanlış, IOException'ı işlemek, ancak yakalanmayan istisnaları atmak için belirli bir istisnayı yakalıyorsa bir İstisna oluşturmalıdır.

Gibi bir şey:

public void method() throws Exception{
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println(e.getMessage());
   }
}

veya

public void method(){
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println("Catching IOException");
           System.out.println(e.getMessage());
   }catch(Exception e){
           System.out.println("Catching any other Exceptions like NullPontException, FileNotFoundExceptioon, etc.");
           System.out.println(e.getMessage());
   }

}


1

Verdiğiniz örnekte, yöntem hiçbir zaman bir IOException oluşturmayacaktır, bu nedenle bildirim yanlıştır (ancak geçerlidir). Tahminimce, orijinal yöntem IOException'ı attı, ancak daha sonra içindeki istisnayı işlemek için güncellendi, ancak bildirim değiştirilmedi.


1

Bu bir cevap değil, yorum, ancak biçimlendirilmiş bir kodla bir yorum yazamadım, bu yüzden yorum burada.

Var diyelim

public static void main(String[] args) {
  try {
    // do nothing or throw a RuntimeException
    throw new RuntimeException("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Çıktı

test
Exception in thread "main" java.lang.RuntimeException: test
    at MyClass.main(MyClass.java:10)

Bu yöntem, herhangi bir İstisnayı "fırlatır", ancak onları fırlatır! İşin püf noktası, atılan istisnaların, yöntemde bildirilmesi gerekmeyen RuntimeExceptions (işaretlenmemiş) olmasıdır. Yöntemin okuyucusu için biraz yanıltıcıdır, çünkü tek gördüğü bir "atma e" dir; beyan ancak istisna atışı bildirimi yok

Şimdi, eğer sahipsek

public static void main(String[] args) throws Exception {
  try {
    throw new Exception("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Yöntemde "atar" istisnalarını bildirmemiz GEREKİR, aksi takdirde derleyici hatası alırız.


Derleyici throws, gerekli olup olmadığına karar vermek için şaşırtıcı derecede karmaşık bir statik analiz yapar .
Brent Bradburn
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.