Hiç atılamayan kontrol edilen istisnalar ile nasıl baş edilir


35

Örnek:

foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");

Kodlama sabit kodlanmış ve doğru olduğundan, yapıcı, şartnamede belirtilen UnsupportedEncodingException öğesini hiçbir zaman atmayacaktır (java uygulaması bozulmadığı sürece, bu durumda yine de kayboldum). Her neyse, Java beni zaten bu istisna ile uğraşmaya zorluyor.

Şu anda, öyle görünüyor

try {
    foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");
}
catch(UnsupportedEncodingException e) { /* won't ever happen */ }

Nasıl daha iyi hale getirileceği hakkında fikrin var mı?


4
Gerçek bir meydan okuma için, bu yakalamanın gerçekten işe yaradığından emin olmak için bir birim testi yazın.
Jay Elston

1
`Yeni ImpossibleException'ı at (" Evreni yeniden başlat. İşler berbat oldu ", e);
Chris Cudmore

1
"Hiç olmayacak" olacak ...

Thorbjørn Ravn Andersen: programı değiştirdikten sonra olabilir, ancak en azından şu anki durumunda, hiçbir girdi verisi istisnayı tetikleyemez.
user281377

Yukarıdaki özel örneğinizde, bir yöntem desteklenip desteklenmeyen bir kodlamayla çağrılıp çağrılmayacağını bilmediğinden bir istisna atılır. Bunun bir yolu, standart bir karakter kümesi verildiğini varsayan ve bir istisna atılacağını ilan etmek zorunda kalmayacak başka bir kurucu olsaydı olurdu.
Ürdün

Yanıtlar:


27

Alışkanlığım, sadece güvenli tarafta olmak, assertavcılığı engellemek. Birisi trydaha sonra bloğun içeriğini değiştirebilir ve kodun başarısız olup olmadığını bilmek ister misiniz?


İyi bir fikir; basit assert false;, çok fazla karışıklık eklemiyor ve toplama bloğuna asla girilmeyeceğini varsaydığımı açıkça gösteriyor.
user281377

5
@ammoQ veya hatta yapmak için bir mesaj ekleyebilirsiniz senin kesinlikle açık niyet: assert false : "should never happen".
Péter Török

13
Daha da iyisi, "Asla olmamalı çünkü Java, ISO-8859-1 karakter grubunun desteklenmesini gerektiriyor."
dan04 15

3
assertiddiaların etkin olduğunu gösterir. Bir atıyorum UnexpectedException(ayrıca yığın izlememe izin verme avantajı da var ...).
Chop

35

Her zaman bir kuruş verilmiş olsaydı, "Bu asla olmamalı" diye bir kayıt / hata gördüm. Ama hala...

Boş tutma blokları, örümceğimin karıncalanma algılarına neden oluyor ve çoğu iyi kod analiz aracı şikayet ediyor. Ne pahasına olursa olsun onları boş bırakmaktan kaçınırdım. Tabii ki, şimdi hatanın asla gerçekleşemeyeceğini biliyorsunuz, ancak bir yıl sonra birileri "ISO-8859-1" adlı global arama yerine geçer ve aniden bir hata bulmanız çok zor olabilir.

assert falseÖneri iyidir, ama iddialar beri devre dışı bırakılabilir zamanında, bunlar hiçbir garantisi vardır. Onun RuntimeExceptionyerine kullanırım. Bunların sınıfları çağırarak yakalanmaları gerekmeyecek ve eğer meydana gelirlerse, tam bilgi vermek için yığın izine sahip olacaksınız.


28

Her zaman böyle yaptım:

try {
    foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");
} catch(UnsupportedEncodingException e) {
    throw new AssertionError(e);
}

Biraz ayrıntılı olabilir (Java ...), ancak en azından imkansız olduğunda bir iddia hatası alırsın.

Java uygulaması bozulursa, mümkün olan en kısa sürede, imkansızı yok saymak yerine, mümkün olduğunca iyi bir hata mesajı almak istersiniz. Java uygulaması kırık olmasa bile, birisi değişmiş olabilir sizin için kod "UTF8"(- olmalıydı ayy "UTF-8"?).

Bu her şeyden önce bir çalışma zamanı istisnası olmalıydı . JDK bu tür yanlış seçimlerle doludur.


4
Asıl kötü karar (veya istersen ihmal), Java'nın gerektirdiği 6 karakter için önceden tanımlanmış bir Charset örneği bulunmamasıdır. foobar = new InputStreamReader(p.getInputStream(), Charset.ISO_8859_1);- Şimdi bu daha iyi olmaz mı ve sonsuza dek hata yapmaktan kaçınır mı?
user281377

3
Guava kütüphanesinde bunlardan tonlarca var. Hayatı kolaylaştırır.

3
Java 1.7+ tanımlanmış karakter kümesi sabitlerine sahiptir: docs.oracle.com/javase/7/docs/api/java/nio/charset/… . Onları şöyle kullanın: StandardCharsets.UTF_8.displayName ()
Michael

4

Eğer bu kodu görebilecek tek geliştirici sizseniz o zaman sorun olmazdı, ama o zaman bunu yapmazsanız gerçek bir olasılık olarak kabul ederdim ya da en azından "asla olmayacak" yorumunu değiştiririm. daha kullanışlı bir şey.


4

Bu istisnaların beni en çok sinirlendiren kısmı, kod kapsamımı bozuyor.

Kapsama konusunda mecbur olduğumda, "asla olmayacak" denemesini / yakalanacağım (... ya da sadece "US-ASCII" yi eklemeyi unutmuş mutant bir JVM kullanıyorsam) kontrol edilen istisnayı burada belirtilen yollardan biriyle değiştiren (genellikle gizli bir mesajla denetlenmeyen bir istisna atma) deneyen / yakalayan ve kontrol edilen istisnayı değiştiren bir sınıf ve yöntem.

Sonra kod kapsama alanım, yardımcı programdan çok etkilendi, ancak kodumun etrafına dağılmış olan bu işleme yapılan tüm referanslarda.

Bazen, tutarlı bir anlambilimsel olan bir sınıftaki işlemler gibi ilerlemeye zaman ayıracağım. Ancak neler olup bittiği takım arkadaşlarım için oldukça açık olduğu için, mümkün olan en iyi tasarım hakkında çok endişelenmeyeceğim ve endişelenmeyeceğim kadar basit tutuyorum.

Bununla birlikte, bahsi geçen bir yorum olarak, Guava ve diğer kütüphanelerin bu acıyı hafifletme yolları vardır - ama bu temelde aynı stratejidir. Can sıkıntısını aşama dışına taşıyın böylece ana kodunuz kapsama alanında değildir.

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.