Java'da doğru yol çözümü: 2 dizeden 2 sayıyı ayrıştırın ve ardından toplamlarını geri getirin


84

Oldukça aptalca bir soru. Kod verildiğinde:

public static int sum(String a, String b) /* throws? WHAT? */ {
  int x = Integer.parseInt(a); // throws NumberFormatException
  int y = Integer.parseInt(b); // throws NumberFormatException
  return x + y;
}

Java'nın iyi olup olmadığını söyleyebilir misin? Bahsettiğim şey, NumberFormatExceptionkontrol edilmeyen bir istisnadır. Sen yok bir parçası olarak belirtmek için sum()imza. Dahası, anladığım kadarıyla, kontrol edilmeyen istisnalar fikri sadece programın uygulamasının yanlış olduğunu işaret etmektir ve daha da önemlisi, kontrol edilmeyen istisnaları yakalamak kötü bir fikirdir, çünkü bu , çalışma zamanında kötü programı düzeltmek gibidir .

Biri lütfen açıklığa kavuşturur mu:

  1. NumberFormatExceptionMetodun imzasının bir parçası olarak belirtmeliyim .
  2. Kendi kontrol edilen istisnamı ( BadDataException) tanımlamalı NumberFormatException, yöntemin içinde işlem yapmalı ve olarak yeniden atmalıyım BadDataException.
  3. Kendi kontrol edilen istisnamı ( BadDataException) tanımlamalı , her iki dizeyi de normal ifadeler gibi doğrulamalı ve BadDataExceptioneşleşmiyorsa atmalıyım.
  4. Senin fikrin?

Güncelleme :

Bir nedenden dolayı kullanmanız gereken açık kaynaklı bir çerçeve olmadığını hayal edin. Yöntemin imzasına bakarsınız ve "Tamam, asla atmaz" diye düşünürsünüz. Sonra bir gün bir istisna olur. Bu normal mi?

Güncelleme 2 :

Benim sum(String, String)kötü bir tasarım olduğunu söyleyen yorumlar var . Kesinlikle katılıyorum, ancak iyi bir tasarıma sahip olsaydık orijinal sorunun asla ortaya çıkmayacağına inananlar için, işte ekstra bir soru:

Problem tanımı şu şekildedir: sayıların Strings olarak saklandığı bir veri kaynağınız var . Bu kaynak XML dosyası, web sayfası, 2 düzenleme kutusu olan masaüstü penceresi olabilir.

Amacınız bu 2 Strings'yi alan mantığı uygulamak, onları ints'ye çevirmek ve "toplam xxx" yazan mesaj kutusu göstermektir.

Bunu tasarlamak / uygulamak için kullandığınız yaklaşım ne olursa olsun , bu 2 iç işlevselliğe sahip olacaksınız :

  1. Dönüştürmek için bir yer Stringiçinint
  2. 2 intsaniye eklediğiniz bir yer

Orijinal gönderimin ana sorusu şudur:

Integer.parseInt()doğru dizenin geçirilmesini bekler . Ne zaman kötü bir dizge geçerseniz , bu , programınızın yanlış olduğu anlamına gelir (" kullanıcınız bir aptal" değil). Bir yandan ZORUNLU semantiğe sahip Integer.parseInt () 'e sahip olduğunuz yerde kod parçasını uygulamanız gerekir ve diğer yandan girdinin yanlış olduğu durumlarda tamam olmanız gerekir - SHOULD anlambilim .

Öyleyse, kısaca: Yalnızca ZORUNLU kütüphanelerim varsa, anlambilimini nasıl uygulayabilirim ?


13
Bu kesinlikle aptalca bir soru değil. Aslında oldukça iyi! Tam olarak emin değilim, hangi seçeneği seçerim.
martin

1
Güncellemenize: Evet, hızlı hata ilkesine göre bu da kötü bir şey olmayabilir.
Johan Sjöberg

1
Martin'e katılıyorum. Java programlamanın en az anlaşılan ve bazı en iyi uygulamaları gerektiren yönlerinden biridir. Bu, O'Reilly'nin "böyle yapılmalı" demesinin yanı sıra konuyla ilgili sayfaların eksikliğinden anlaşılabilir.
James P.

2
Aslında bu harika bir soru.
Chris Cudmore

1
Harika soru! Ayrıca harika yanıtlar da verdi: D
Kheldar

Yanıtlar:


35

Bu güzel bir soru. Keşke daha çok insan böyle şeyler düşünse.

IMHO, çöp parametrelerinden geçtiyseniz kontrol edilmeyen istisnalar atmanız kabul edilebilir.

Genel olarak konuşursak, BadDataExceptionprogram akışını kontrol etmek için İstisnaları kullanmamalısınız çünkü atmamalısınız. İstisnalar istisnai durumlar içindir. Yönteminizi arayanlar , dizelerinin sayı olup olmadığını aramadan önce bilebilirler , bu nedenle çöpün içeri girmesi önlenebilir ve bu nedenle bir programlama hatası olarak düşünülebilir , bu da kontrol edilmeyen istisnaları atmanın uygun olduğu anlamına gelir.

Bildirime gelince throws NumberFormatException- bu o kadar kullanışlı değil, çünkü NumberFormatException'ın işaretlenmemiş olması nedeniyle çok az kişi fark edecek. Bununla birlikte, IDE'ler bunu kullanabilir ve try/catchdoğru şekilde sarmayı teklif edebilir . İyi bir seçenek de javadoc kullanmaktır, örneğin:

/**
 * Adds two string numbers
 * @param a
 * @param b
 * @return
 * @throws NumberFormatException if either of a or b is not an integer
 */
public static int sum(String a, String b) throws NumberFormatException {
    int x = Integer.parseInt(a); 
    int y = Integer.parseInt(b); 
    return x + y;
}

DÜZENLENDİ : Yorumcular
geçerli puanlar verdiler . Bunun nasıl kullanılacağını ve uygulamanızın genel tasarımını düşünmeniz gerekir.

Yöntem her yerde kullanılacaksa ve tüm arayanların sorunları ele alması önemliyse, yöntemi kontrol edilen bir istisna atıyor (arayanları sorunlarla başa çıkmaya zorlamak), ancak kodu try/catchbloklarla karıştırmak olarak bildirin .

Öte yandan, bu yöntemi güvendiğimiz verilerle kullanıyorsak, bunu yukarıdaki gibi açıklayın, çünkü patlaması beklenmez ve esasen gereksiz try/catchblokların kod karmaşasından kaçınırsınız .


6
Sorun şu ki, kontrol edilmeyen istisnalar genellikle göz ardı edilir ve çağrı yığınınızı süzebilir ve uygulamanızın altında ne olduğuna dair hiçbir fikri olmayan bölümlerinde hasara yol açabilir. Soru gerçekten hangi kod bitinin girdinin geçerli olup olmadığını kontrol etmesi gerektiğidir.
G_H

1
@ G_H bir noktaya sahip. Java öğreticileri şunu söyler: "Bir istemcinin bir istisnadan kurtarması makul bir şekilde bekleniyorsa, bunu kontrol edilmiş bir istisna yapın. Bir istemci istisnadan kurtarmak için hiçbir şey yapamazsa, onu kontrol edilmeyen bir istisna yapın". Soru, nerede RuntimeExceptionele alınmalı ? Arayan kişi mi olmalı, yoksa İstisna yukarı mı kalmalı? Eğer öyleyse nasıl ele alınmalı?
James P.

1
Buna kısmen cevap vermek için gördüğüm iki yaklaşım var: Birincisi, Exceptionsalt katmanlardan müdahale etmek ve onları son kullanıcı için daha anlamlı olan daha yüksek seviyeli İstisnalara sarmak ve ikincisi, içinde başlatılabilen yakalanmamış bir istisna işleyicisi kullanmak. uygulama başlatıcısı.
James P.

2
JavaDoc'ta NumberFormatException özelliğine sahip IMHO çok daha önemlidir. Maddeye koymak throwsgüzel bir ektir, ancak gerekli değildir.
Dorus

3
To "kendi dizeleri numara veya değilse bu kadar çöp içinde önlenebilir olduğunu geçirmeden, diyoruz önce yöntemine arayanlar bilebilir" Bu gerçekten doğru değil. Bir dizenin int olarak ayrıştırıldığını doğrulamanın tek basit yolu, onu denemektir. Bazı önceden kontroller yapmak isteyebilirsiniz, ancak tam kontrol oldukça PITA'dır.
maaartinus

49

Kanımca istisna mantığını olabildiğince ele almak tercih edilir. Bu yüzden imzayı tercih ederim

 public static int sum(int a, int b);

Senin yöntem imzası ile ben ediyorum değil herhangi bir değişiklik. Ya sen

  • Üretici algoritmanızı doğrulayabileceğiniz hatalı değerler kullanarak programlama yoluyla
  • veya örneğin kullanıcı girdisinden değerler göndererek, bu durumda modül doğrulamayı gerçekleştirmelidir

Bu nedenle, bu durumda istisna işleme bir dokümantasyon sorunu haline gelir .


4
Bunu severim. Kullanıcıyı sözleşmeye uymaya zorlar ve yöntemin tek bir şey yapmasını sağlar.
Chris Cudmore

Bu yöntemin kullanımının a + b yapan kullanıcıdan ne kadar farklı olduğunu anlamıyorum. Bu yönteme neden ihtiyacımız var?
Swati

4
@Swati: Bence bu bir örnek , şeyleri basitçe göstermek için harika bir teknik. Toplam yöntemi, myVeryComplicatedMethodWhichComputesPhoneNumberOfMyIdealMatchGirl (int myID, int myLifeExpectancy) olabilir ...
Kheldar

3
Burada tamamen katılıyorum. sumiki sayı bekleyen bir işlev, iki sayı almalıdır. Bunları elde etme şekliniz sumişlevle ilgili değildir . Mantığınızı doğru şekilde ayırın . Yani bunu bir tasarım sorunuyla ilişkilendiririm.
c00kiemon5ter

5

Numara 4. Verildiği gibi, bu yöntem tamsayılar alması gereken parametre olarak dizeleri almamalıdır. Bu durumda (java taşmak yerine sarmaladığından) bir istisna olasılığı yoktur.

 x = sum(Integer.parseInt(a), Integer.parseInt(b))

ne anlama geldiğinden çok daha net x = sum(a, b)

İstisnanın mümkün olduğunca kaynağa (girişe) yakın olmasını istiyorsunuz.

1-3 seçenekleriyle ilgili olarak, bir istisna tanımlamazsınız çünkü arayanların kodunuzun başarısız olamayacağını varsaymasını beklersiniz, METODUNUZA BENZERSİZ, bilinen hata koşulları altında ne olacağını tanımlamak için bir istisna tanımlarsınız. Yani, başka bir nesnenin etrafında sarmalayıcı olan bir yönteminiz varsa ve bir istisna atarsa ​​sonra onu iletin. Yalnızca istisna yönteminize özgüse, özel bir istisna atmalısınız (örneğinizde frex, toplamın yalnızca pozitif sonuçlar döndürmesi gerekiyorsa, o zaman bunu kontrol etmek ve bir istisna atmak, diğer yandan java ise uygun olacaktır. sarmak yerine bir taşma istisnası attıysanız, bunu iletirsiniz, imzanızda tanımlamaz, yeniden adlandırmaz veya yiyemezsiniz).

Sorunun güncellenmesine yanıt olarak güncelleme:

Öyleyse, kısaca: Yalnızca ZORUNLU kütüphanelerim varsa, anlambilimini nasıl uygulayabilirim?

Bunun çözümü, ZORUNLU kütüphaneyi sarmak ve bir ÖNERİLEN değer döndürmektir. Bu durumda, bir Tamsayı döndüren bir işlev. Bir dizge alan ve bir Tamsayı nesnesi döndüren bir işlev yazın - ya çalışır ya da boş döndürür (guava'nın Ints.tryParse gibi). Doğrulamanızı operasyonunuzdan ayrı yapınız, operasyonunuz devreye girmelidir. Geçersiz girişiniz olduğunda işleminizin varsayılan değerlerle çağrılıp çağrılmayacağı, spesifikasyonlarınıza bağlı olacaktır - bununla ilgili en çok söyleyebileceğim şey, bu kararı vereceğiniz yerin operasyonda olması gerçekten olası değildir. yöntem.


Buradaki fikrin nedir? Ben olsa bile aynı sorunu uğrayacaksın sum(int, int)ve parseIntFromString(String). Her iki durumda da aynı işlevselliği elde etmek için, 2 çağrı parseIntFromString()ve 1 çağrı olan bir kod parçası yazmam gerekecek sum(). Sizin için mantıklıysa, bu durumu düşünün - orijinal sorunun bakış açısından hiçbir fark görmüyorum.
Andrey Agibalov

@ loki2302: Konu, arayan kişinin bir sayı olmadığında hangi davranışın uygun olduğuna karar vermesidir. Ayrıca, hata denetimi yapmazlarsa, başarısızlık değerin atandığı yere bir adım daha yakın gerçekleşir - hata ayıklama amacıyla atamaya ne kadar yakınsa hata ayıklama o kadar kolay olur. TDD yapıyorsanız, arayan için uygun birim testini yazmayı kaçırmanız daha olasıdır. Temel olarak, x yönteminde bir sayı olması beklenen bir dizeye sahip olmak istemezsiniz ve ardından 5 sınıf ve 20 yöntem çağrısı, onu bir sayı işlemeye çalıştığınızda bir istisna atar.
jmoreno

Ben anlamadım Gerçekte bir arayüz sağlamanın int sum(String, String)asla mümkün olmadığını mı söylemeye çalışıyorsunuz ?
Andrey Agibalov

1
@ loki2302: Gösterilen kod göz önüne alındığında, mümkün olabilir ama kötü bir fikir. Dizedeki sayı "2", "iki", "dos", "deux", "zwo" kelimelerinin hepsinin aynı kabul edileceği bir kelime olabilirse, bu imza uygun olacaktır. Ancak olduğu gibi, yönteme iki dizi verilir ve bunları tamsayı olarak ele alır. Neden bunu yapmak istedin? Bu kötü bir fikir.
jmoreno

2
@ loki2302: Çöpü geçerken kontrol edilmeyen bir istisna atmanın uygun olduğunu söyleyerek yanıtı kabul ettiniz, ancak güçlü yazılmış bir dilin amacı çöpün geçmesini ÖNLEMEK. Bir dizenin her zaman bir tamsayı değeri olmasını bekleyen bir yönteme sahip olmak sadece sorun istemektir. Integer.parseInt bile bununla iyi başa çıkmaz (girişin beklenmesi GEREKEN bir istisna kötüdür, .Net'in tamsayısı TryParse yöntemi çok daha iyidir, ancak Java'nın bir out parametresinin olmaması onu biraz kullanışsız kılar).
jmoreno

3

1. NumberFormatException'ı yöntemin imzasının bir parçası olarak belirtmeliyim.

Ben öyle düşünüyorum. Güzel bir belge.

2. Kendi denetlenen istisnamı (BadDataException) tanımlamalı, NumberFormatException yöntemini işlemeli ve BadDataException olarak yeniden atmalıyım.

Bazen evet. Kontrol edilen istisnaların bazı durumlarda daha iyi olduğu düşünülmektedir, ancak onlarla çalışmak oldukça PITA'dır. Bu nedenle birçok çerçeve (örn. Hazırda Bekletme) yalnızca çalışma zamanı istisnalarını kullanır.

3. Kendi denetlenen istisnamı (BadDataException) tanımlamalı, her iki dizeyi de normal ifadeler gibi doğrulamalı ve eşleşmezse BadDataException'ımı atmalıyım.

Asla. Daha fazla iş, daha az hız (istisnanın kural olmasını beklemediğiniz sürece) ve hiç kazanç yok.

4. Fikriniz?

Hiç yok.


2

Nr 4.

Yöntemi hiç değiştirmeyeceğimi düşünüyorum. İstisnadan iş mantığıyla incelikle kurtarabileceğim bir bağlamda olduğum yerde, çağırma yönteminin etrafına veya yığın izlemede daha yüksek bir deneme yakalama koyardım.

Aşırı olduğunu düşündüğüm için 3 numarayı yapmam.


2

Yazdıklarınızın başka biri tarafından (API gibi) tüketileceğini varsayarsak, o zaman 1 ile gitmelisiniz, NumberFormatException özellikle bu tür istisnaları iletmek içindir ve kullanılmalıdır.


2
  1. Öncelikle kendinize sormanız gerekiyor, yöntemimin kullanıcısının yanlış veri girme konusunda endişelenmesi mi gerekiyor, yoksa doğru verileri girmesi mi bekleniyor (bu durumda String). Bu beklenti, sözleşmeli tasarım olarak da bilinir .

  2. ve 3. Evet, muhtemelen BadDataException'ı tanımlamalısınız veya daha iyisi NumberFormatException gibi bazı istisnaları kullanmalısınız, bunun yerine standart mesajı gösterilecek şekilde bırakmalısınız. Yöntemde NumberFormatException'ı yakalayın ve orijinal yığın izlemesini dahil etmeyi unutmadan mesajınızla birlikte yeniden atın.

  3. Duruma göre değişir, ancak muhtemelen NumberFormatException'ı bazı ek bilgilerle yeniden atarak giderdim. Ayrıca, bunun için beklenen değerlerin ne olduğuna dair bir javadoc açıklaması olmalıdır.String a, String b


1

İçinde bulunduğunuz senaryoya çok bağlı.

Durum 1. Kodda hata ayıklayan her zaman sizsiniz ve başka hiç kimse ve istisna kötü bir kullanıcı deneyimine neden olmaz

Varsayılan NumberFormatException öğesini atın

Örnek Olay2: Kod son derece sürdürülebilir ve anlaşılır olmalıdır

Kendi istisnanızı tanımlayın ve fırlatırken hata ayıklama için çok daha fazla veri ekleyin.

Kötü girişte yine de istisnaya gideceği için normal ifade kontrollerine ihtiyacınız yok.

Üretim seviyesinde bir kod olsaydı, benim fikrim birden fazla özel istisna tanımlamak olurdu, örneğin

  1. Sayı biçimi istisnası
  2. Taşma istisnası
  3. Boş istisna vb ...

ve tüm bunları ayrı ayrı ele alın


1
  1. Bunun yanlış girişte olabileceğini açıkça belirtmek için bunu yapabilirsiniz. Bu durumla başa çıkmayı hatırlamak için kodunuzu kullanan birine yardımcı olabilir. Daha spesifik olarak, bunu kodda kendiniz işlemediğinizi veya bunun yerine belirli bir değer döndürmediğinizi açıkça belirtiyorsunuz. Tabii ki, JavaDoc bunu da netleştirmelidir.
  2. Yalnızca, arayan kişiyi kontrol edilen bir istisna ile ilgilenmeye zorlamak istiyorsanız.
  3. Bu aşırılık gibi görünüyor. Bozuk girişi tespit etmek için ayrıştırmaya güvenin.

Genel olarak, bir NumberFormaException denetlenmez çünkü doğru ayrıştırılabilir girdinin sağlanması beklenir. Giriş doğrulama, halletmeniz gereken bir şeydir. Ancak, girdiyi gerçekten ayrıştırmak, bunu yapmanın en kolay yoludur. Yöntemi olduğu gibi bırakabilir ve belgelerde doğru girişin beklendiği ve işlevinizi arayan herhangi birinin kullanmadan önce her iki girişi de doğrulaması gerektiği konusunda uyarabilirsiniz.


1

Herhangi bir istisnai davranış, belgelerde açıklığa kavuşturulmalıdır. Ya başarısızlık durumunda bu yöntemin özel bir değer döndürdüğünü belirtmeli ( nulldönüş türünü olarak değiştirerek Integer) ya da durum 1 kullanılmalıdır. Yöntemin imzasında açıkça belirtilmesi, kullanıcının başka yollarla doğru dizeleri sağlaması durumunda onu yok saymasına izin verir, ancak yine de yöntemin bu tür bir başarısızlığı kendi başına ele almadığı açıktır.


1

Güncellenen sorunuza cevap verin.

Evet, "sürpriz" istisnalarının olması tamamen normaldir. Programlamaya yeni başladığında birinin aldığı tüm çalışma zamanı hatalarını düşünün.

e.g ArrayIndexOutofBound

Ayrıca her döngü için ortak bir sürpriz istisna.

ConcurrentModificationException or something like that

1

Çalışma zamanı istisnasının, tasarım ve kullanılabilirlik açısından algılanmasına izin verilmesi gerektiği cevabına katılsam da, onu NumberFormatException olarak atmak yerine bir IllegalArgumentException içine sarmak iyi bir fikir olacaktır. Bu daha sonra, yönteminizin sözleşmesini daha açık hale getirir ve bu sayede bir istisna attığı için kendisine yasadışı bir argüman geçirildiğini bildirir.

"Düşünün, bu bir sebepten dolayı kullanmanız gereken açık kaynaklı bir çerçeve değil. Yöntemin imzasına bakıp" Tamam, asla atmıyor "diye düşünüyorsunuz. Sonra, bir gün, bir istisna var . Bu normal mi?" yönteminizin javadoc'u her zaman yönteminizin davranışını ortaya çıkarmalıdır (ön ve son kısıtlamalar). Bir boşluğa izin verilmiyorsa javadoc'un, hiçbir zaman yöntem imzasının bir parçası olmamasına rağmen boş bir işaretçi istisnasının atılacağını söylediği söz toplama arayüzlerinin satırlarını düşünün.


2
NumberFormatException, IllegalArgumentException'ın bir alt sınıfıdır, bu nedenle bu kaydırma hiçbir bilgi eklemez.
Don Roby

bu, istisnanın olduğu gibi ortaya çıkabileceği anlamına gelir (bu durumda nfe zaten yasa dışı bir argüman istisnasıdır) ve çağrı hiyerarşisinde bir yerlerde yasadışı argümanlarla başa çıkmak için genel bir işlem olabilir. bu nedenle, bu argümanların kullanıcı tarafından iletildiği bir örnek olsaydı, yasadışı argümanlar için tüm işlemleri saracak ve kullanıcıyı bu konuda bilgilendirecek genel bir kod olabilirdi.
Scorpion

1

İyi bir java uygulamasından bahsederken, bence her zaman daha iyidir

  • Denetlenmemiş istisnayı işlemek için, ardından onu ve özel bir kontrol edilmemiş istisnayı analiz edin.

  • Ayrıca, özel kontrol edilmemiş istisna atarken, istemcinizin anlayabileceği İstisna mesajını ekleyebilir ve ayrıca orijinal istisnanın yığın izini yazdırabilirsiniz.

  • Özel istisnayı kontrol edilmediğinden "fırlatır" olarak bildirmeye gerek yoktur.

  • Bu şekilde, kontrol edilmeyen istisnaların kullanımını ihlal etmiyorsunuz, aynı zamanda kodun müşterisi istisnanın nedenini ve çözümünü kolayca anlayacaktır.

  • Ayrıca java-doc'ta düzgün şekilde belgelemek iyi bir uygulamadır ve çok yardımcı olur.


1

Sanırım amacınıza bağlı, ancak en azından bunu belgeleyeceğim:

/**
 * @return the sum (as an int) of the two strings
 * @throws NumberFormatException if either string can't be converted to an Integer
 */
public static int sum(String a, String b)
  int x = Integer.parseInt(a);
  int y = Integer.parseInt(b);
  return x + y;
}

Veya java.lang.Integer sınıfı için Java kaynak kodundan bir sayfa alın:

public static int parseInt(java.lang.String string) throws java.lang.NumberFormatException;

1

Google'ın 'Guava' kitaplığı veya Apache'nin 'Doğrulayıcı' kitaplığı ( karşılaştırma ) tarafından uygulanan giriş doğrulama modeline ne dersiniz ?

Tecrübelerime göre, bir işlevin parametrelerini işlevin başında doğrulamak ve uygun olduğunda İstisnalar atmak iyi bir uygulama olarak kabul edilir.

Ayrıca, bu sorunun büyük ölçüde dilden bağımsız olduğunu düşünürdüm. Buradaki 'iyi uygulama', geçerli olabilecek veya olmayabilecek parametreler alabilen işlevlere sahip tüm diller için geçerli olacaktır.


1

"Oldukça aptalca bir soru" şeklindeki ilk cümlenin çok alakalı olduğunu düşünüyorum. Neden ilk başta o imzayla bir yöntem yazasın ki? İki dizgeyi toplamak mantıklı mı? Çağıran yöntem iki dizeyi toplamak istiyorsa, geçerli ints olduklarından emin olmak ve yöntemi çağırmadan önce bunları dönüştürmek, çağıran yöntemin sorumluluğundadır.

Bu örnekte, çağırma yöntemi iki Dizeyi bir int'e dönüştüremiyorsa, birkaç şey yapabilir. Bu toplamın hangi katmanda gerçekleştiğine gerçekten bağlıdır. Dize dönüşümünün ön uç koduna çok yakın olacağını varsayıyorum (doğru şekilde yapıldıysa), bu durumda 1. büyük olasılıkla:

  1. Bir hata mesajı ayarlayın ve işlemeyi durdurun veya bir hata sayfasına yönlendirin
  2. Yanlış döndür (yani, toplamı başka bir nesneye koyar ve döndürmesi gerekmez)
  3. Önerdiğiniz gibi bazı BadDataException oluşturun, ancak bu iki sayının toplamı çok önemli olmadığı sürece, bu aşırıdır ve yukarıda belirtildiği gibi, bu muhtemelen kötü bir tasarımdır çünkü dönüşümün yanlış yerde yapıldığını gösterir.

1

Bu sorunun pek çok ilginç cevabı var. Ama yine de şunu eklemek istiyorum:

Dizge ayrıştırması için her zaman "normal ifadeler" kullanmayı tercih ederim. Java.util.regex paketi bize yardımcı olmak için var. Bu yüzden asla istisna yaratmayan böyle bir şeyle sonuçlanacağım. Bir hata yakalamak istersem özel bir değer döndürmek bana kalmıştır:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public static int sum(String a, String b) {
  final String REGEX = "\\d"; // a single digit
  Pattern pattern = Pattern.compile(REGEX);
  Matcher matcher = pattern.matcher(a);
  if (matcher.find()) { x = Integer.matcher.group(); }
  Matcher matcher = pattern.matcher(b);
  if (matcher.find()) { y = Integer.matcher.group(); }
  return x + y;
}

Görüldüğü gibi, kod biraz daha uzun, ancak istediğimizi halledebiliriz (ve x ve y için varsayılan değerler belirleyebilir, else cümlelerinde ne olacağını kontrol edebilir, vb ...) Daha genel bir dönüşüm bile yazabiliriz dizeleri geçirebileceğimiz rutin, varsayılan dönüş değerleri, derlenecek REGEX kodu, atılacak hata mesajları, ...

Umarım faydalıdır.

Uyarı: Bu kodu test edemedim, bu yüzden lütfen olası söz dizimi sorunlarını özür dilerim.


1
Java hakkında mı konuşuyoruz? Nedir Integer.matcher? privatedeğişken içinde yöntem? Eksik ()bir sürü eksik, IFS için ;, x, ybeyan değil, matcheriki kez ilan ...
user85421

Nitekim Carlos aceleyle yaptım ve dediğim gibi hemen test edemedim. Afedersiniz. Normal ifade yapma şeklini göstermek istedim.
Louis

Tamam, ancak bu, NumberFormatException ile ilgili sorunu çözmez - ana soru IMO - ( Integer.matcher.group()olması gerektiği varsayılarak Integer.parseInt(matcher.group()))
user85421

0

Bu sorunla karşı karşıyasınız çünkü kullanıcı hatalarının uygulamanın özünde çok derinlere yayılmasına izin vermişsinizdir ve kısmen de Java veri türlerini kötüye kullanmışsınızdır.

Kullanıcı girişi doğrulama ve iş mantığı arasında daha net bir ayrım yapmalısınız, doğru veri tipini kullanın ve bu sorun kendiliğinden ortadan kalkacaktır.

Gerçek şu ki, semantiği Integer.parseInt()biliniyor - birincil amacı geçerli tam sayıları ayrıştırmak . Açık bir kullanıcı girişi doğrulama / ayrıştırma adımını kaçırıyorsunuz.

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.