Java insanları neden istisnaları sık sık sessizce kullanır?


81

Daha önce hiç ciddi bir Java kodlaması yapmadım, ancak mevcut becerilerime (Delphi & C #) dayalı olarak sözdizimini, kitaplıkları ve kavramları öğrendim. Anlayamadığım bir şey ise, bunun printStackTracegibi istisnaları sessizce tüketen çok fazla kod görmüş olmam :

    public void process() {
        try {
            System.out.println("test");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

Hemen hemen her Java makalesinde ve karşılaştığım projede buna benzer bir kod var. Bildiğim kadarıyla bu çok kötü. İstisna, hemen hemen her zaman şu şekilde dış bağlama iletilmelidir:

    public void process() {
        try {
            System.out.println("test");
        } catch(Exception e) {
            e.printStackTrace();
            throw new AssertionError(e);
        }
    }

Çoğu zaman istisna, temel çerçeveye (örneğin Java Swing) ait olan en dış döngüde ele alınmalıdır. Java dünyasında böyle kodlama neden norm gibi görünüyor? Şaşırdım.

Geçmişime bağlı olarak, printStackTrace'i tamamen kaldırmayı tercih ederim . İşlenmemiş bir aka RuntimeException(veya daha iyisi AssertionError) olarak yeniden atar , sonra en uygun yerde yakalayıp kaydederdim : en dıştaki çerçeve döngüsü.

    public void process() {
        try {
            System.out.println("test");
        } catch(Exception e) {
            throw new AssertionError(e);
        }
    }

56
Yığın izi yazdırıldığında gerçekten sessiz olmadığını söyleyebilirim :)
willcodejavaforfood

13
Isaac Waller'dan alıntı yapabilir miyim? "Ama programınız, büyük olasılıkla tanımlanmamış durumda, çıkmıyor ve devam ediyor"
Sake

15
@willcodejavaforfood, Yorumunuz çok fazla oy aldı ve bu beni tipik java zihniyetiyle ilgili daha da şaşırttı.
Sake

13
@willcodejavaforfood - arayanın bakış açısından sessizdir. Arayan kişinin herhangi bir şey olduğu hakkında hiçbir fikri yok. Şimdi kasıt buysa, sorun değil, ama genel olarak bu kötü haber. Ayrıca - bir uygulamada ne olduğunu düşünün - kullanıcı çıktıyı asla görmeyecektir (java konsolunu açmadıkları sürece, ki bu asla değildir). Tamam, artık kimse uygulama kullanmıyor;) Servletm için benzer - son kullanıcı hiçbir şey olduğunu bilmiyor - sadece bir günlükte saklanıyor.
Scott Stanchfield

4
Java'da istisna atma o kadar yaygındır ki, çoğu Java kodlayıcı bunları görmezden gelir çünkü doğru hata yakalamayı yaparsanız, çok daha fazla kod yazmanız gerekir ... yani temelde tüm bu java programcıları bunu yapar çünkü tembeldirler.
Trevor Boyd Smith

Yanıtlar:


203

Her zaman şöyle düşünmüşümdür, bu aşağıdaki senaryoya benzer:

"Bir adam vurulur.

Nefesini tutuyor ve otobüse binmek için yeterli güce sahip.

10 mil sonra adam otobüsten iner, birkaç blok yürür ve ölür. "

Polis cesedin yanına geldiğinde, ne olduğu hakkında hiçbir fikirleri yok. Sonunda olabilirler ama çok daha zordur.

Daha iyisi:

"Bir adam vurulur ve anında ölür ve vücut tam olarak cinayetin gerçekleştiği yerde yatar."

Polis geldiğinde, tüm kanıtlar yerinde olur.

Bir sistem başarısız olacaksa, daha hızlı başarısız olmak daha iyidir

Soruyu ele almak:

  1. Cehalet.
      +
  2. Tembel hayvan

DÜZENLE:

Tabii ki, catch bölümü kullanışlıdır.

İstisna dışında bir şey yapılabiliyorsa, yapılması gereken yer orasıdır.

Muhtemelen bu verilen kod için bir istisna DEĞİLDİR, muhtemelen beklenen bir şeydir (ve benim benzetmemde kurşun geçirmez bir ceket gibidir ve adam ilk etapta çekimi bekliyordu).

Ve evet, yakalama , soyutlamaya uygun istisnaları atmak için kullanılabilir.


2
İstisnaları yutmak başarısız değildir, hızlı başarısız olmayı boşverin. Öte yandan, yöntem sözleşmeniz bir basamak dizesi olan bir parametreye sahipse ve bunu bir Tamsayı olarak ayrıştırıyorsanız, ParseException'ı yutabilirsiniz. Belirli bir işlevsellik yazıyorsanız, başarısız olan bu işlevsellik için özel bir istisna tanımlayın, ardından istisnaları yakalayın ve özel istisnanızı (bağımsız değişken olarak orijinal istisna ile) atın. Daha sonra anlamlı davranışların meydana gelebileceği bir yerde hızlı bir şekilde başarısız olabilir (kullanıcıya göster, e-posta gönder, sadece günlüğe kaydet, bu sunucu dizisinden çık, vb.).
JeeBee

21
Bir dakika ... Önce gülmeyi bırakmalıyım ... Tamam ... Bu şimdiye kadar gördüğüm bir sorunun açık ara en eğlenceli cevabıydı. Bu noktayı çok iyi anlıyor. İşlem için istisnayı "zincirden yukarı" geçirmek çok yararlı olsa da, en azından önce istisnayı yakalamak ve sonra onu geçmek daha iyidir, böylece bazı yararlı bilgiler dahil edilebilir.
Bay Will

Bunun istisnası hata değildir. Bir istisna, vurulan adamdır ve daha sonra olayı bir notta detaylandırır ve en yakın cinayet ekibine uçmak için eğitilmiş bir taşıyıcı güvercine iliştirir.
Jherico

13
@Oscar, eğer yapabilirsem +100. Kötü istisna yönetimi tembellik değil, Cehalet ve KÖTÜLÜK sonucudur. Tembellik = mümkün olduğunca az çaba. İstisnaları ele almadaki aptallık daha fazla çalışmaya neden olur, onu azaltmaz ... elbette, genellikle başkası için daha fazla çalışmaya neden olur, bu yüzden "tembel" görünür.
James Schek

1
Söylediğinizi anlıyorum Oscar, ancak istisnayı ele almak veya bunu kaydetmek size istisnanın gerçekleştiğini gösteriyor. Zincirin sonuna kadar geri atarsanız, hangi yöntemin nihayetinde istisnayı çağırdığını bilmenizi sağlar.
Mauro

33

Genellikle bu, IDE'nin, sorun teşkil eden kodu, bu istisna işleme ile bir dene-yakala bloğuna saran yararlı bir 'hızlı düzeltme' sunmasından kaynaklanır. Buradaki fikir, aslında bir şeyler YAPMANIZ, ancak tembel geliştiricilerin yapmamasıdır.

Bu kötü bir biçim, şüphesiz.


2
Kabul edildi, verilen örnek, // FIXME: yorumu kaldırılmış olarak Eclipse'in varsayılan hızlı düzeltmesine benziyor.
JeeBee

2
"Bu kötü bir form, şüphesiz " dedin ve% 100 katılıyorum. Bununla birlikte, diğer bazı cevaplar ve yorumlar, java geliştiricilerinin bu çok büyük kısmının (inanıyorum) arkasındaki felsefede beni çok meraklandırıyor.
Sake

4
Eclipse'in orada sert bir şey yapmasını gerçekten isterdim. E.printStackTrace () gibi; System.exit (1);
Adam Jaskiewicz

4
IDE ayarlarımı RuntimeException olarak yeniden atan bir yakalama gövdesi oluşturmak için değiştirdim. Bu çok daha iyi bir varsayım.
Esko Luontola

6
İstisnanın hiçbir zaman olmaması gerektiğinden eminsem, niyetimi belgelemek için genellikle RuntimeException yerine bir AssertionError atarım.
Esko Luontola

20

Bu klasik bir saman adam argümanıdır . printStackTrace()bir hata ayıklama aracıdır. Bunu bir blogda veya bir dergide gördüyseniz, bunun nedeni yazarın istisna işlemeden başka bir noktayı açıklamakla daha çok ilgilenmesidir. Bunu üretim kodunda gördüyseniz, bu kodun geliştiricisi cahil ya da tembeldi, başka bir şey değil. "Java dünyasında" yaygın bir uygulama örneği olarak görülmemelidir.


1
yani pro-programcıların üretimde değil blog veya dergide kötü kod yazması uygun mu? id, üretimde kötü kod yazmayı tercih eder. gerçekten akıllı bir adam printStackTrace kullanıyorsa, insanları onu kullanmaya ikna eder. istisna kodunun 8 karakter daha uzun olduğunu anlıyorum, ama ...
IAdapter

8
@ABCDE: Kesinlikle katılmıyorum. Üretimde kötü kod yazmayı mı tercih edersiniz? Çalışması gereken kod bu! Blog ve dergi makalelerinin bir noktayı göstermesi beklenir. Hata işleme konu değilse, o zaman sadece dağınıklık olabilir. Pek çok yazar, makalelerde büyük ölçüde basitleştirilmiş hata işlemeyi kullanır veya hiç kullanmaz. Bu izlenecek bir örnek değil.
Bill the Lizard

19
  1. Java sizi tüm İstisnaları açıkça işlemeye zorlar. Kodunuzun çağırdığı bir yöntem FooException ve BarException'ı atacak şekilde bildirilirse, kodunuzun bu istisnaları işlemesi (veya atması) ZORUNLUdur . Bunun tek istisnası RuntimeException , ninja gibi sessiz olan .
  2. Pek çok programcı tembeldir (ben de dahil) ve yığın izini yazdırmak çok kolaydır.

7
Ancak programınız büyük olasılıkla tanımlanmamış durumda, çıkmıyor ve devam ediyor.
Isaac Waller

5
İstisna türünü biliyorsanız, eyalet nasıl tanımlanamaz? Bu sevimli küçük bir alıntı, ama genellikle program DEVAM EDEBİLİR ve ZORUNDADIR. Tüm uygulamanın bir istisna nedeniyle çökmesini istemezsiniz - kullanıcıya söyleyin ve ondan her ne ise onu tekrar yapmasını isteyin.
GreenieMeanie

2
İstisna, en dış düzeyde düzgün bir şekilde ele alınırsa uygulama çökmez.
Sake

2
İstisnaların en az yarısı "RuntimeExceptions" dır, sanki sadece bir tane varmış gibi ses çıkarırsınız. Ve sessiz değil ve yakalanmamış RutimeException bir yığın izi yazdıracak ve programınızı çökertecektir.
Bill K

@greenieMeanie Genel olarak geliştirme aşamasında, en ufak bir problemle sert bir şekilde çökmesini istersiniz - geliştiricilerin bir çağrıyı mahvetmesine izin vermeyin - HİÇBİR ŞEYİ affetmeyin. Öte yandan, onu gönderirken, tam tersi yapmak istersiniz. Her istisnayı görünmez bir şekilde günlüğe kaydedin ve kurtarmak ve devam etmek için elinizden gelenin en iyisini yapın (Java gerçekten çok iyi).
Bill K

12

Bunun yapılmasının genellikle 2 nedeni olduğunu görüyorum

  1. Programcı tembeldi
  2. Programcı oraya bir giriş noktasını korumak istedi (doğru veya yanlış)

Bunun Java ile sınırlı bir fenomen olduğuna inanmıyorum. Bu tür kodlamaları C # ve VB.Net'te de sıklıkla gördüm.

Yüzeyde oldukça şok edici ve korkunç görünüyor. Ama gerçekten yeni bir şey değil. İstisnalara karşı hata kodu dönüş değerleri kullanan C ++ uygulamalarında her zaman oluşur. Aradaki fark, potansiyel olarak ölümcül bir dönüş değerini göz ardı etmenin, void döndüren bir işlevi çağırmaktan gerçekten farklı görünmemesidir.

Foo* pFoo = ...;
pFoo->SomeMethod(); // Void or swallowing errors, who knows?

Bu kod daha iyi görünür, ancak SomeMethod () bir HResult döndür diyor olsaydı, anlamsal olarak bir istisnayı yutmaktan farklı olmazdı.


3
Özellikle bu soru için Sebep 1'in Sebep 2'den çok daha yaygın olduğunu düşünüyorum
matt b

2
@matt b, kabul etti. Bugünlerde düzelttiğim hataların önemli bir kısmından tembellik sorumludur.
JaredPar

Bir hata kodunu yok saymak çok daha hızlı bir görüştür ve çok daha az standart kod kullanır!
gbjbaanb

11

çünkü Kontrol Edilmiş İstisnalar başarısız bir denemedir

(belki printStackTrace () gerçek sorun mu? :)


17
Başarısız bir deney değiller. Aslında onları beğendim! Diğer cevapların da işaret ettiği gibi, programcılar tembel olma eğilimindedir ve hata durumlarını görmezden gelir. Kontrol edilen istisnalar sizi onlarla ilgilenmeye zorladığından, genel olarak daha iyi bir koda sahip olacaksınız. (Programcı sessizce onları görmezden gelmiyorsa). Ayrıca, tembel
olmasanız

5
kontrol edilen istisnalar birkaç nedenden dolayı başarısızlıktır: bazılarını kontrol edin mindview.net/Etc/Discussions/CheckedExceptions
dfa

2
+1 daha fazla anlaşamadı. Kontrol edilen istisnalar genellikle kodu daha az güvenli hale getirir ve bu nasıl yapıldığına dair bir örnektir.
cletus

2
Kontrol edilen istisnalar kesinlikle mükemmel değildir, ancak sizi bazen işlerin plana göre gitmediği gerçeğiyle yüzleşmeye zorlarlar. Kontrol
edilmeyen istisnalar

2
@Peter Lawrey: kontrol edilen istisnalar bir başarısızlıktır çünkü şaşırtıcı Swing çerçevesiyle gelenler gibi çok zeki insanlar üzerlerine kusup onları kullanmayı reddediyorlar. Ve Joshua Bloch gibi insanların veya Bahar çerçevesinin arkasındaki kişilerin "bunları nasıl doğru şekilde kullanacaklarını bilmediklerinden" çok şüpheliyim. Elbette, kontrol edilen bir istisnayla doğru şekilde başa çıkabilirsiniz . Asıl kırıklık, bir yerlerde birinin atmanın kabul edilebilir bir uygulama olduğunu düşünmesidir.
SözdizimiT3rr0r

6

Bu tür gevşek hata işleme davranışının Java programcıları için temel bir şey olduğunu ima eden tondan biraz içerlediğimi söylemeliyim. Elbette, Java programcıları diğer tüm programcılar gibi tembel olabilir ve Java popüler bir dildir, bu nedenle muhtemelen çok sayıda kod yutma istisnası göreceksiniz.

Ayrıca, başka yerlerde de belirtildiği gibi, kişisel olarak benim bununla ilgili bir sorunum olmasa da, Java'nın zorunlu olarak kontrol edilen istisnalar beyanında anlaşılır hayal kırıklıkları var.

Sanırım bir sorunum var, bağlamı göz önünde bulundurma zahmetine girmeden web'deki bir dizi makale ve kod parçacığını karıştırıyorsunuz. Gerçek şu ki, belirli bir API'nin nasıl çalıştığını veya bir şeye nasıl başlayacağınızı açıklamaya çalışan teknik bir makale yazarken, büyük olasılıkla kodun bazı yönlerini atlayabilirsiniz - hata işleme doğrudan değildir Gösterdiğiniz şeyle ilgili, özellikle örnek senaryoda istisnanın meydana gelmesi olası değilse, olası bir elden çıkarma adayıdır.

Bu türden makaleler yazan insanlar makul bir sinyal-gürültü oranını korumak zorundadırlar ve daha doğrusu, bu, geliştirdiğiniz dil hakkında bazı temel bilgileri bildiğinizi varsaymaları gerektiği anlamına gelir; hatalarla nasıl başa çıkılacağı ve bir sürü başka şey. Bir makaleye rastlarsanız ve uygun hata kontrolünün olmadığını fark ederseniz, sorun değil; sadece bu fikirleri üretim kodunuza dahil ettiğinizde (ama elbette, hiçbir zaman tam kodun kendisini değil, değil mi?), yazarın mantıklı bir şekilde dışarıda bıraktığı tüm bu bit ve çıkıntıları en çok geliştirdiğiniz şeye uygun.

Bu tür konulara hiç geri dönmeden esinti veren çok yüksek seviyeli giriş makaleleri ile ilgili bir sorunum var, ancak lütfen Java programcılarının hata işlemeyle ilgili belirli bir "zihniyetinin" olmadığını unutmayın; Tüm problemleriyle uğraşmakla uğraşmayan çok sayıda sevgili C # programcısını da biliyorum.


Ancak kullanarak üst düzey bir makale yazmak try {...} catch (IOException e) {}aptalcadır (ve bir TODO yardımcı olmaz). Yeni başlayanları aynı şeyi yapmaya kesinlikle yanıltacaktır. Dahası, yazmaktan çok daha fazlasıdır throws IOExceptionki bu çoğu zaman doğrudur. Belki kağıt başına bir kez, bu mümkün değildir ve sonra yazmak throw wrap(e)(tanımlamak sıkıcı olmadan wrap) iyi bir çözümdür. Java'da eğildiğim ilk şeylerden biri, sessizce yutmanın korkunç bir şey olduğu ve çok dikkatli olduğum için geçici olarak bile yapmıyorum (çökmek bile uzun vadede çok daha iyi).
maaartinus

5

Bir System.out print veya e.printStackTrace () - System.out kullanımını ima eder, genellikle kırmızı bir bayraktır, yani birisi gayretli bir iş yapmaya zahmet etmedi. Masaüstü Java Uygulamaları dışında, çoğu Java uygulamasının günlük kaydı kullanması daha iyidir.

Bir yöntemin başarısızlık modu işlemsiz ise, sebebini (ve varlığını) kaydetseniz de kaydetmeseniz de bir istisna yemekte son derece iyidir. Daha tipik olarak, ancak, catch cümlesinin bir tür istisnai eylemde bulunması gerekir.

Bir istisnayı yeniden fırlatmak, işin bir kısmını gerekli bilgilerin hala mevcut olduğu bir seviyede temizlemek için yakalama özelliğini kullandığınızda veya istisnayı arayan için daha uygun bir istisna türüne dönüştürmeniz gerektiğinde en iyi şekilde yapılan bir şeydir.


3

Sadece yakalama bloğu gerçekten boşsa sessizce tüketilir.

Makalelere gelince, istisnalarla nasıl başa çıkılacağının yanı sıra başka bir noktayı kanıtlama konusunda muhtemelen daha ilginçtirler. Sadece doğrudan konuya girmek ve mümkün olan en kısa koda sahip olmak isterler.

Açıkçası haklısınız, istisnalar en azından 'yok sayılacaklarsa' kaydedilmelidir.


3

Diğerlerinin de belirttiği gibi, bunu görmenizin nedeni üç nedenden biridir:

  1. Bir IDE, try-catch bloğunu oluşturdu
    • Kod kopyalandı ve yapıştırıldı
    • Geliştirici yığın izini hata ayıklamaya koydu ancak istisnayı doğru şekilde ele almak için asla geri dönmedi

Son nokta, ortaya çıkma olasılığı en düşük olan noktadır. Bunu söylüyorum çünkü kimsenin bu şekilde hata ayıklayacağını düşünmüyorum. Bir hata ayıklayıcı ile kod üzerinde adım atmak, hata ayıklamanın çok daha kolay bir yoludur.

Bir catch bloğunda ne yapılması gerektiğine dair en iyi açıklama Joshua Bloch tarafından Etkili Java'nın 9. Bölümünde bulunabilir .


2

C #'da tüm istisnalar çalışma zamanı istisnalarıdır, ancak Java'da çalışma zamanı istisnaları vardır ve metotlarınızda yakalamanız veya bildirmeniz gereken istisnalar kontrol edilir. Sonunda "atışlar" olan herhangi bir yöntemi çağırırsanız, orada belirtilen istisnaları yakalamanız veya yönteminizin de bu istisnaları bildirmesi gerekir.

Java Makaleleri genellikle yalnızca yığın izini yazdırır veya bir yorum içerir, çünkü istisna işleme makalenin konusuyla ilgisizdir. Projelerde ise istisna türüne bağlı olarak bununla ilgili bir şeyler yapılmalıdır.


2

Programcı işini doğru yaparsa bunu çok sık görmelisiniz. İstisnayı görmezden gelmek kötü, kötü bir uygulamadır! Ancak bazılarının bunu yapmasının bazı nedenleri ve daha uygun çözümler var:

  • "Bu olmayacak!" Elbette, bazen bu İstisnanın olmayacağını "biliyorsunuz", ancak oluşan İstisnayı sadece görmezden gelmek yerine "neden" olarak tekrar bir çalışma zamanı istisnası atmaya daha uygun. İddiaya girerim gelecekte bir ara olur. ;-)

  • Prototip Oluşturma Kodu Eğer işe yarayıp yaramadığını görmek için sadece yazı yazıyorsanız, oluşabilecek tüm İstisnaları yok saymak isteyebilirsiniz. Bu, biraz tembel yakalama yaptığım tek durum (Atılabilir). Ancak kod yararlı bir şeye dönüşecekse, uygun istisna işlemeyi dahil ediyorum.

  • "Ne yapacağımı bilmiyorum!" Çok fazla kod gördüm, özellikle istisnaları yutan kütüphane kodu, çünkü uygulamanın bu katmanında düzgün işlem yapılamıyor. BUNU YAPMAYIN! İstisnayı yeniden atın (ya yöntem imzasına bir throws cümlesi ekleyerek ya da istisnayı kütüphaneye özel bir cümle içine alarak).


3
Yakalamayı görmek (Atılabilir) beni utandırdı.
Bill the Lizard

2
Kesinlikle. Ben sadece catch (Throwable) kullanıyorum ya da etrafta oynuyorsam kodda Throwable atar. "Gerçek" kod bunu içermemelidir! dönem.
Malax

Kabul. Küçülüyorum çünkü daha önce gördüm Başka bir geliştirici, catch (Atılabilir) yazdığınızı görürse, çok ileri gitti! :)
Bill the Lizard

1
Kod süreci kapatsa bile (Throwable) en üst düzeyde yakalamak istersiniz. Bir iş parçacığı eksikken aksamaya çalışmak en iyi fikir olmayabilir.
Tom Hawtin - tackline

2

Her zaman bunu iletmeli veya gerçek dünya bağlamında uygun şekilde kullanmalısınız. Pek çok makale ve öğretici, daha önemli noktalara ulaşmak için kodlarını basitleştirecek ve basitleştirilmesi en kolay şeylerden biri hata işlemedir (yaptığınız şey, hata işleme hakkında bir makale yazmak değilse :)). Java kodu istisna işlemeyi kontrol edeceğinden, basit bir sessiz (veya günlük ifadesi) yakalama bloğu koymak, çalışan bir örnek sağlamak için en basit yöntemdir.

Bunu örnek kod dışında bir yerde bulursanız, kodu TDWTF'ye iletmekten çekinmeyin, ancak şimdiye kadar çok fazla örneği olabilir :)


2

Korkarım java programcılarının çoğu İstisnalar ile ne yapacaklarını bilmiyor ve bunu her zaman "nominal" durumu kodlamalarını yavaşlatan bir sıkıntı olarak görüyorlar. Elbette tamamen yanılıyorlar, ancak istisnalarla doğru şekilde başa çıkmanın önemli olduğu konusunda onları ikna etmek zor. Böyle bir programcıyla her karşılaştığımda (sık sık oluyor) ona iki okuma girişi veriyorum:

  • ünlü Java'da Düşünme
  • Barry Ruzek'in kısa ve ilginç bir makalesine buradan ulaşabilirsiniz: www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html

Bu arada, bir RuntimeException içine gömülü olarak yeniden yazmak için yazılmış bir istisnayı yakalamanın aptalca olduğuna kesinlikle katılıyorum:

  • yakalarsan, ELLE.
  • aksi takdirde, ele alacağınız / edemeyeceğiniz olası istisnaları eklemek için yöntem imzanızı değiştirin, böylece arayan kişi bunu kendi başına yapma şansına sahip olur.

Ben% 100 Bruce
Eckel'e

2

Kontrol edilen istisnaların ve arayüzlerin kombinasyonu, kodun asla fırlatılmayan istisnaları işlemesi gerektiği duruma yol açar. (Aynısı normal kalıtım için de geçerlidir, ancak daha yaygındır ve arayüzlerle açıklanması daha kolaydır)

Neden: Bir arayüzün uygulanması, arayüz spesifikasyonunda tanımlananlar dışındaki istisnaları atamaz (kontrol edilemez). Bu nedenle, arayüzü uygulayan bir sınıfın hangi yöntemlerinin gerçekte bir istisna atması gerekebileceğini bilmeyen bir arabirimi oluşturan kişiler, tüm yöntemlerin en az bir tür istisna atabileceğini belirtebilir. Örnek: JDBC, burada her şeyin ve büyükannesinin SQLException atacağı bildirilir.

Ancak gerçekte birçok gerçek uygulama yöntemi başarısız olamaz, bu nedenle hiçbir koşulda bir istisna oluşturmazlar. Bu yöntemleri çağıran kod, yine de bir şekilde istisnayı "ele almalıdır" ve bunun en kolay yolu, istisnayı yutmaktır. Hiç kimse kodunu, hiçbir zaman yürütülemeyen görünüşte işe yaramaz hata işleme ile karıştırmak istemez.


1
IMHO, çalışma zamanı hataları gibi istisnaları yakalamak ve yeniden atmak için bir dil kısaltması olmalıdır. Bu tür bir kısaltmanın not edilmesi, hem kodda hem de davranışta bu tür istisnaların "beklenmedik" koşulları temsil ettiği kabul edilmesi gerektiğini açıkça ortaya koyacaktır. Yutma kötüdür, çünkü bir istisna atılırsa bir şeyler ciddi şekilde yanlıştır ve arama kodu bunu öğrenmelidir.
supercat

supercat: Bu fikri beğendim, ancak kontrol edilen istisnaların (IMO sorgulanabilir) faydasını iptal edebilir.
Erich Kitzmueller

Kontrollü olma, istisna sınıflarından ziyade yakalama / fırlatma sitelerinin ve istisna örneklerinin bir özelliği olsaydı daha iyi olurdu, böylece kontrol edilen istisnalar aynı sınıfın kontrol edilmemiş istisnaları olarak yayılabilirdi, ancak sarma ve yeniden atma bile üzerinde büyük bir gelişme olurdu. statüko ve kolayca yeni bir özellik olarak eklenebilir. Kendi başına kontrol edilmiş bir istisna atabilen bir yöntemin, aynı istisnayı attığı bildirilen ancak gerçekten bunu yapması beklenmeyen diğer yöntemleri çağırdığı durumlarda özellikle yararlı olacaktır . İkinci yöntemlerden biri atarsa ​​...
2014

... dış yöntemden atılan istisnayı işlemeyi bekleyen bir arayan, arayanın beklediği koşulu temsil etmeyeceğinden, iç yöntemler tarafından atılan bir istisnayı yakalamamalıdır. Sıfırdan bir çalışma zamanı çerçevesi tasarlasaydım, kontrol edilen ve kontrol edilmeyen istisnalar için farklı bir mekanizma kullanırdım, öyle ki kontrol edilen istisnalar başarılı bir fonksiyon çağrısına hafif bir ek yük getirir, ancak atıldığında kontrol edilmeyen istisnalara göre çok daha az ek yüke sahip olur (diğer şeylerin yanı sıra , kontrol edildiği gibi yakalanan bir istisna, yığın izine sahip olmaz).
supercat

1

Belirtildiği gibi, printStackTrace () 'i çağırmak gerçekten sessiz işlem değildir.

İstisnanın bu şekilde "yutulmasının" nedeni, istisnayı zincirden geçirmeye devam ederseniz, istisnayı bir yerde halletmeniz veya uygulamanın çökmesine izin vermeniz gerektiğidir . Bu nedenle, bir bilgi dökümü ile oluştuğu seviyede ele almak, onu bir bilgi dökümü ile en üst seviyede ele almaktan daha kötü değildir.


1

Tembel uygulaması - gerçekten ondan başka bir şey yok.

Genellikle parmak işinizi artırmak yerine istisnayı gerçekten önemsemediğinizde yapılır.


1

Kontrol edilen bir istisnayı yeniden atmanın daha iyi bir fikir olduğuna katılmıyorum. Yakalama, elleçleme anlamına gelir; yeniden atmanız gerekiyorsa, yakalamamalısınız. Bu durumda throws cümlesini yöntem imzasına eklerdim.

Kontrol edilmiş bir istisnayı kontrol edilmemiş bir istisnaya sarmanın (örneğin, Spring'in kontrol edilen SQLException'ı kontrol edilmemiş hiyerarşisinin bir örneğine sarması) kabul edilebilir olduğunu söyleyebilirim.

Günlük kaydı, işlem olarak düşünülebilir. Örnek, konsola yazmak yerine log4j kullanarak yığın izlemeyi günlüğe kaydedecek şekilde değiştirildiyse, bu onu kabul edilebilir kılar mı? Pek bir değişiklik değil, IMO.

Asıl mesele, neyin istisnai olduğu ve kabul edilebilir bir kurtarma prosedürüdür. İstisnadan kurtulamazsanız, yapabileceğiniz en iyi şey arızayı bildirmektir.


1

Lütfen asla, asla, kontrol edilmiş bir istisnayı kontrol edilmemiş bir istisnaya sarmayın.

Kendinizi yapmanız gerektiğini düşünmediğiniz istisnalarla uğraşırken bulursanız, benim tavsiyem muhtemelen yanlış soyutlama seviyesinde çalıştığınızdır.

Açıklayacağım: işaretli ve kontrol edilmemiş istisnalar, çok farklı iki canavardır. Kontrol edilen istisnalar, eski hata kodlarını döndürme yöntemine benzer ... evet, bunlar hata kodlarından biraz daha zahmetlidir, ancak avantajları da vardır. Kontrol edilmeyen istisnalar programlama hataları ve kritik sistem arızalarıdır ... başka bir deyişle istisnai istisnalar. Bir istisnanın ne olduğunu açıklamaya çalışırken, birçok insan bu iki, çok farklı durumdaki farkı kabul etmedikleri için tam bir karmaşa içine düşer.


AssertionError'da sarmalama benim için çok önemli. AssertionError, IMO gibi her yerde geçerli olan soyutlamadır.
Sake

Açıklayacağım: işaretli ve kontrol edilmemiş istisnalar, çok farklı iki canavardır. Kontrol edilen istisnalar, eski hata kodlarını döndürme yöntemine benzer ... evet, bunların üstesinden gelmeleri hata kodlarından biraz daha zahmetlidir, ancak avantajları da vardır. Kontrol edilmeyen istisnalar programlama hataları ve kritik sistem arızalarıdır ... diğer bir deyişle istisnai istisnalar. Bir istisnanın ne olduğunu açıklamaya çalışırken, birçok insan bu iki, çok farklı durumdaki farkı kabul etmedikleri için tam bir karmaşa içine düşer.
CurtainDog

Muhtemelen, sizin de ifade ettiğiniz gibi, tam bir karmaşa içinde olanlardanım. Ancak, asıl amacım, onu durdurma seçeneğiniz varken neden infazın devam etmesine izin vermenizdir. (AssertionError ile veya tercih ederseniz, arayüzünüzü ekstra İstisna içerecek şekilde değiştirin.
Sake

1
Bu cevabın birincil iddiasına daha fazla katılamazdım. Detaylandırmanın faydaları var.
Lawrence Dol

@CurtainDog: Kontrol edilen istisnalar "beklenen" sorunlar içindir. Eğer yöntem x tür durumlarda, ortaya beklemediğini x çağırır (işaretli) bazı durumlarda FooException ve yöntem y, atar sonra bu tür vakalar eğer do ortaya, onlar temsil beklenmedik problemi; Çağrı yığınının yukarısında a'yı bekleyen bir şey olsa bile FooException, mevcut durum a FooExceptionatıldığında yukarı yöndeki arayanın bekleyeceği durumla eşleşmeyecektir .
supercat

1

Çünkü henüz bu numarayı öğrenmediler:

class ExceptionUtils {
    public static RuntimeException cloak(Throwable t) {
        return ExceptionUtils.<RuntimeException>castAndRethrow(t);
    }

    @SuppressWarnings("unchecked")
    private static <X extends Throwable> X castAndRethrow(Throwable t) throws X {
        throw (X) t;
    }
}

class Main {
    public static void main(String[] args) { // Note no "throws" declaration
        try {
            // Do stuff that can throw IOException
        } catch (IOException ex) {
            // Pretend to throw RuntimeException, but really rethrowing the IOException
            throw ExceptionUtils.cloak(ex);
        }
    }
}

bu güzel bir numara, ama şahsen, 'yeni ServiceUnavailableException (örn.)' gibi bir sebeple daha spesifik bir istisna atmayı tercih ederim
Greg

Apache'nin ExceptionUtils'in rethrow yöntemi tam olarak bunu yapar. Bu iyi bir numara. github.com/apache/commons-lang/blob/master/src/main/java/org/…
Lluis Martinez

1

İstisnaların gerçek noktası, hata işlemeyi basitleştirmek ve hata tespitinden ayırmaktır. Bu, hataları hata kodlarıyla temsil etmenin tersidir, burada hata işleme kodu her yere dağılmıştır ve başarısız olabilecek her çağrının dönüş kodu için kontrol edilmesi gerekir.

Eğer istisna bir hatayı temsil ediyorsa (ki bu çoğu durumda) genellikle bunu halletmenin en mantıklı yolu kurtarmayı ve idareyi bir üst katmana bırakmaktır. Farklı bir istisnanın yeniden atılması, buna bazı anlamlı anlamlar eklenirse dikkate alınmalıdır, yani, bu hata olağandışı bir sistem hatası / geçici (ağ oluşturma) problemi / bu, istemci veya sunucu tarafı hatası vb.

Tüm hata işleme stratejileri arasında en bilgisiz olanı, hata mesajını gizlemek veya basitçe yazdırmak ve hiçbir şey olmadıkça ilerlemektir.


Sun millet, kodun daha açık olmasını istedi ve programcıları hangi istisnaların hangi yöntemle atılabileceğini yazmaya zorladı. Doğru hareket gibi görünüyordu - prototip olduğu için herhangi bir yöntem çağrısından ne beklemesi gerektiğini herkes bilir (bu türden bir değer döndürebilir veya belirtilen sınıflardan birinin (veya alt sınıfının) bir örneğini atabilir).

Ancak pek çok cahil Java programcısı ile ortaya çıktığı üzere, artık istisna işlemeyi bir geçici çözüme ihtiyaç duyan bir dil hatası / "özellik" olarak ele alıyorlar ve en kötü veya neredeyse en kötü şekilde kod yazıyorlar:

  • Hata, onunla ne yapılacağına karar vermeye uygun olmayan bağlamda hemen ele alınır.
  • Sessizce görüntülenir veya yok sayılır ve daha fazla kodun düzgün çalışma şansı olmasa bile hesaplama devam eder.
  • Yöntemi arayan kişi, başarılı bir şekilde bitirip bitirmediğini ayırt edemez.

"Doğru yol" nasıl yazılır?

  • Yöntem başlığında atılabilecek her temel istisna sınıfını belirtin. AFAICR Eclipse bunu otomatik olarak yapabilir.
  • Yöntem prototipindeki fırlatma listesini anlamlı hale getirin. Uzun listeler anlamsızdır ve "istisna atma" tembeldir (ancak istisnalar hakkında fazla endişelenmediğinizde kullanışlıdır).
  • "Yanlış şekilde" yazarken, basit "Özel Durum Atma" çok daha iyidir ve "try {...} catch (Exception e) {e.printStackTrace ();}" den daha az bayt alır.
  • Gerekirse zincirleme istisnayı yeniden atın.

0

İstisnanızın mevcut yöntemin kapsamı dışında işlenmesini istiyorsanız, onu gerçekten yakalamanıza gerek yoktur, bunun yerine yöntem imzasına 'atar' ifadesi eklersiniz.

Gördüğünüz dene / yakala ifadeleri, yalnızca programcının istisnayı açıkça yerine getirmeye ve bu nedenle onu daha fazla atmamaya karar verdiği kodda bulunur.


1
Doğru değil - bir arayüz yöntemi uyguluyorsanız veya 'atar' bildirimi olmayan bir üst sınıf yöntemini geçersiz kılıyorsanız, o zaman bir tane ekleyemezsiniz. Bu durumlarda, istisnayı bir RuntimeException içinde sarmalamanız veya yutmanız gerekir.
Martin McNulty

0

Bence geliştiriciler, belirli bir bağlamda "doğru şeyi yapmanın" önemini de dikkate almaya çalışıyorlar. Çoğu zaman kodu çöpe atmak veya istisnayı yukarı doğru yaymak hiçbir şey satın almaz çünkü istisna ölümcüldür, "yanlış şeyi yaparak" da zaman ve emekten tasarruf edebilirsiniz.


0

Genellikle ondan kurtulamadığınızda bir istisnayı yutarsınız, ancak bu kritik değildir. İyi bir örnek, bir veritabanı bağlantısını kapatırken fırlatılabilen IOExcetion'dur. Bu olursa gerçekten çökmek istiyor musun? Bu yüzden Jakarta'nın DBUtil'lerinin closeSilently yöntemleri var.

Şimdi, kurtaramayacağınız, ancak kritik (genellikle programlama hataları nedeniyle) kontrol edilen istisna olarak, onları yutmayın. İstisnaların, sorunun kaynağına mümkün olan en yakın şekilde günlüğe kaydedilmesi gerektiğini düşünüyorum, bu yüzden printStackTrace () çağrısının kaldırılmasını önermem. Yalnızca bu istisnaları iş yönteminizde bildirmek zorunda kalmamak için bunları RuntimeException'a dönüştürmek isteyeceksiniz. CreateClientAccount () throws ProgrammingErrorException (SQLException okuyun) gibi üst düzey iş yöntemlerine sahip olmak gerçekten mantıklı değil, sql'nizde yazım hataları varsa veya kötü dizinlere erişiyorsanız yapabileceğiniz hiçbir şey yoktur.


0

Deneyimlere göre, bir istisnayı yutmak çoğunlukla basılmadığında zararlıdır. Çarpışmanız durumunda dikkat çekmenize yardımcı olur ve bunu bazen kasıtlı olarak yaparım, ancak istisnayı yazdırmak ve devam etmek sorunu bulmanızı ve düzeltmenizi sağlar ve yine de genellikle aynı kod tabanı üzerinde çalışan diğer kişileri olumsuz etkilemez. .

Aslında Fail-Fast / Fail-ZARD ile ilgileniyorum, ancak en azından yazdırın. Bir istisnayı gerçekten "Yerseniz" (ki bu gerçekten hiçbir şey yapmamaktır: {}) Birisinin onu bulması GÜNLERE mal olur.

Sorun şu ki, Java sizi geliştiricinin atılmayacağını bildiği veya atılıp atılmayacağını umursamadığı birçok şeyi yakalamaya zorluyor. En yaygın olanı Thread.sleep () 'dir. Burada iş parçacığı sorunlarına izin verebilecek boşluklar olduğunun farkındayım, ancak genellikle bunu kesintiye uğratmadığınızı bilirsiniz. Dönem.


0

Catch Exception kullanılmasının birçok nedeni olabilir. Çoğu durumda bu kötü bir fikirdir çünkü RuntimeExceptions'ı da yakalarsınız - ve bundan sonra temeldeki nesnelerin hangi durumda olacağını bilmiyorsunuz? Beklenmedik koşullarda her zaman zor olan budur: kodun geri kalanının daha sonra başarısız olmayacağına güvenebilir misiniz?

Örneğiniz yığın izini yazdırır, böylece en azından temel nedenin ne olabileceğini bilirsiniz. Daha büyük yazılım projelerinde, bunları kaydetmek daha iyi bir fikirdir. Ve umalım ki günlük bileşeni istisnalar atmasın ya da sonsuz bir döngüye girebilirsin (bu muhtemelen JVM'nizi öldürecektir).


0

Kontrol edilmiş bir istisnanız varsa ve bunu bir yöntemde işlemek istemiyorsanız, yalnızca yöntemin istisnayı atmasını sağlamalısınız. İstisnaları yalnızca onunla yararlı bir şey yapacaksanız yakalayın ve ele alın. Kullanıcıların istisnaları aramak için günlükleri okumak için nadiren zamanları olduğundan veya bir istisna atılırsa ne yapacaklarını bildiklerinden, kitabımda sadece giriş yapmak pek kullanışlı değil.

İstisnayı sarmak bir seçenek olsa da, bunu yapmanızı önermem; var olan bir arayüzle eşleşmesi için farklı bir istisna atıyorsunuz veya böyle bir istisnanın atılmasının hiçbir yolu yok.

BTW: Kontrol edilen bir istisnayı yeniden atmak istiyorsanız, bunu aşağıdakilerle yapabilirsiniz:

try {
   // do something
} catch (Throwable e) {
   // do something with the exception
   Thread.currentThread().stop(e); // doesn't actually stop the current thread, but throws the exception/error/throwable
}

Not: Bunu yaparsanız, derleyici bu durumda sizin için bunu yapamayacağından, yöntemin atış bildiriminin doğru olduğundan emin olmalısınız.


Sadece FTR: Thread#stop()kullanımdan kaldırıldı ve bu arada devre dışı bırakıldı (atıyor UnsupportedOperationException).
maaartinus

-2

çünkü en iyi uygulamadır. Herkesin bildiğini sanıyordum.
ama soğuk gerçek şu ki, istisnalar dışında kimse nasıl çalışılacağını gerçekten anlamıyor. C hata teslim tarzı çok daha mantıklıydı.


1
Sırf çok sayıda geliştiricinin istisnaları karıştırmaması "hata dönüşünü" daha iyi hale getirmez. Hataları ele almanın C yolu, korkunç derecede hataya açık (amaçlanan) bir mekanizmadır. İstisnaları yutmak (bu örnekte olduğu gibi, sessizce değil), dönüş değerini kontrol etmeden C'de bir işlevi çağırmaya benzer. Sonuç aynı - program "hatalar" devam ediyor. Bu örnek, Java hata işlemesini kötü C olarak yapma durumudur.
Lawrence Dol,
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.