Bir İstisna Yakalamak ve Yeniden Geri Almak, ancak Bu bir İstisna Değil


10

Ben böyle bir şey bakarak kod tökezledi:

void run() {
    try {
        doSomething();
    } catch (Exception ex) {
        System.out.println("Error: " + ex);
        throw ex;
    }
}

void doSomething() {
    throw new RuntimeException();
}

Bu kod beni şaşırtıyor çünkü run()-method bir fırlatma yeteneğine sahip gibi görünüyor Exception, çünkü onu yakalayıp Exceptiondaha sonra tekrar atıyor , ancak yöntemin atılacağı bildirilmedi Exceptionve görünüşe göre olması gerekmiyor. Bu kod iyi derlenir (en azından Java 11'de).

Benim beklentim -tode ilan etmek throws Exceptionzorunda run()kalacaktı.

Ek bilgi

Benzer şekilde, eğer doSomethingatmak ilan edilir IOExceptiondaha sonra sadece IOExceptionbeyan edilmesi gerekmektedir run()rağmen, kullanılan yöntem Exceptionyakalandı ve rethrown edilir.

void run() throws IOException {
    try {
        doSomething();
    } catch (Exception ex) {
        System.out.println("Error: " + ex);
        throw ex;
    }
}

void doSomething() throws IOException {
    // ... whatever code you may want ...
}

Soru

Java genellikle netliği sever, bu davranışın arkasındaki neden nedir? Hep böyle miydi? Java Dil Spesifikasyonu'ndaki nedir, run()yöntemin throws Exceptionyukarıdaki kod snippet'lerinde bildirilmesine gerek yoktur ? (Eğer eklersem, IntelliJ beni Exceptionasla atılmadığı konusunda uyarır ).


3
İlginç. Hangi derleyiciyi kullanıyorsunuz? IDE derleyicisi ise, o zaman kontrol edin javac- Eclipse derleyicisinin daha yumuşak olduğu durumlarda çalışıyorum.
M. Prokhorov

2
Bu davranışı openjdk-8 üzerinde çoğaltabilirim. Özellikle -source 1.6bayrağın derlenmesi beklendiği gibi bir derleme hatası oluşturur. Kaynak uyumluluğu 7 ile derleniyor yok değil derleme hatası yükseltmek
Vogel612

1
Java 7'den beri derleyici daha akıllı görünüyor ve atılabilecek gerçek istisna üzerinde daha fazla kontrol yapıyor.
michalk

2
Bu soru yinelenen bir yanıt değildir ve yanıt In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions : 1. 1. The try block is able to throw it. 2. There are no other preceding catch blocks that can handle it. 3. It is a subtype or supertype of one of the catch clause's exception parameters.
verdiğim

2
Şu anda işaretlenmiş olan kopya kesinlikle ilgilidir, ancak yeterince ayrıntılı bir yanıt IMO'su sağlamaz. Orada bir JLS link yorumlarda cevap hayır bilgilerin onun dışında, orada.
Simon Forsberg

Yanıtlar:


0

Sorunuzda JLSsorduğunuz gibi tarama yapmadım, bu yüzden lütfen bu cevabı bir tuz tanesi ile alın. Bir yorum yapmak istedim, ama çok büyük olurdu.


Bazen komik buluyorum javac, bazı durumlarda ("sizin durumunuzda olduğu gibi" ne kadar "akıllı"), ama daha sonra uğraşmak için başka birçok şey bırakıyor JIT. Bu durumda, derleyici sadece bir RuntimeExceptionyakalanacağını "söyleyebilir" . Bu açık, attığın tek şey bu doSomething. Kodunuzu biraz değiştirirseniz:

void run() {
    try {
        doSomething();
    } catch (Exception ex) {
        Exception ex2 = new Exception();
        System.out.println("Error: " + ex);
        throw ex2;
    }
}

farklı bir davranış göreceksiniz, çünkü şimdi yakaladığınızla ilişkili olmayan, attığınız javacyeni bir şey olduğunu söyleyebilirsiniz Exception.

Ancak işler ideal olmaktan uzaktır, derleyiciyi tekrar "kandırabilirsiniz":

void run() {
    try {
        doSomething();
    } catch (Exception ex) {
        Exception ex2 = new Exception();
        ex2 = ex;
        System.out.println("Error: " + ex);
        throw ex2;
    }
}

IMO, çünkü ex2 = ex;tekrar başarısız olmamalı, ama öyle.

Bunun derlenmesi durumunda javac 13+33


Bazı bağlantılarda, birinin catch bloğunda yakalanan istisnayı yeniden atarsanız, derleyicinin akıllı olamaması koşuluyla okudum. Bu durumda benzer bir şeyin geçerli olduğunu varsayıyorum. Derleyici, ex2istisnanın atılacağını, başlangıçta bir olarak oluşturulduğunu bilir, Exceptionancak daha sonra yeniden atanır exve bu nedenle derleyici akıllı olamaz.
Simon Forsberg

@SimonForsberg tutkusu olan biri JLSgelip bunu kanıtlamak için gerekli alıntıları yapabilir; maalesef bende yok.
Eugene

Kayıt için, yakalama istisnasının kendisine ( ex = ex;) yeniden atanmasını içerecek şekilde catch bloğunu değiştirdiğimde , sezgisel tarama artık uygulanmaz. Bu davranış, 7'den 11'e ve muhtemelen 13'ten tüm kaynak düzeyleri için geçerli gibi görünüyor
Vogel612

Aynı şekilde yinelenen bu soruya bir göz atın . Bu ve olası dup'ın dup'ı onu açıklar ve ayrıca JLS'ye bağlanır.
michalk
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.