Integer.parseInt () 'i kapsüllemenin iyi bir yolu


93

Integer.parseInt()String'i int türüne dönüştürmek için sıklıkla kullandığımız bir projem var . Bir şeyler ters gittiğinde (örneğin, Stringbir sayı değil, harf aveya her neyse), bu yöntem bir istisna atacaktır. Ancak, kodumdaki istisnaları her yerde ele almak zorunda kalırsam, bu çok çabuk çirkin görünmeye başlar. Bunu bir yönteme koymak isterim, ancak, dönüşümün yanlış gittiğini göstermek için nasıl temiz bir değer döndürüleceğine dair hiçbir fikrim yok.

C ++ 'da, bir int işaretçisi kabul eden ve yöntemin kendisinin doğru veya yanlış döndürmesine izin veren bir yöntem oluşturabilirdim. Ancak bildiğim kadarıyla bu Java'da mümkün değil. Doğru / yanlış değişkeni ve dönüştürülen değeri içeren bir nesne de oluşturabilirim, ancak bu da ideal görünmüyor. Aynı şey küresel bir değer için de geçerli ve bu bana çoklu iş parçacığı ile ilgili bazı sorunlar verebilir.

Peki bunu yapmanın temiz bir yolu var mı?


İlk karakter ... haricinde dizedeki karakterlerin tümü ondalık basamak olmalıdır . Kodun her yerinde istisnaları işlemek yerine, ayrıştırma yöntemini çağırmadan önce dize biçimini kontrol edin.
Lightman

Tüm geçerli 32 bit işaretli tam sayıları ve geçersiz olanların hiçbirini yakalayacak bir normal ifade yazmak neredeyse imkansızdır. 2147483647 yasal intiken 2147483648 yasal değildir.
Seva Alekseyev

Yanıtlar:


142

Ayrıştırma başarısızlığında dönen bir Integeryerine bir döndürebilirsiniz .intnull

Java'nın dahili olarak atılan bir istisna olmadan bunu yapmanın bir yolunu sunmaması utanç verici - istisnayı gizleyebilirsiniz (yakalayarak ve boş döndürerek), ancak yüzlerce ayrıştırıyorsanız yine de bir performans sorunu olabilir. binlerce bitlik kullanıcı tarafından sağlanan veri.

DÜZENLE: Böyle bir yöntem için kod:

public static Integer tryParse(String text) {
  try {
    return Integer.parseInt(text);
  } catch (NumberFormatException e) {
    return null;
  }
}

textBoş ise bunun ne yapacağından emin olmadığımı unutma. Bunu göz önünde bulundurmalısınız - eğer bu bir hatayı temsil ediyorsa (yani kodunuz geçersiz bir değeri iletebilir, ancak hiçbir zaman boş geçmemelidir), o zaman bir istisna atmanın uygun olduğunu; bir hatayı temsil etmiyorsa, muhtemelen başka herhangi bir geçersiz değer için yapacağınız gibi sadece boş döndürmelisiniz.

Başlangıçta bu cevap kurucuyu kullandı new Integer(String); artık Integer.parseIntbir boks operasyonu kullanıyor; bu şekilde küçük değerler önbelleğe alınan Integernesnelere kutulanarak bu durumlarda daha verimli hale gelecektir.


1
Bu nasıl yardımcı olur? Çağrı sitesi şunları gerektirecektir: <b> temp = tryParse (...); eğer (temp! = Null) {hedef = sıcaklık; } else {kurtarma eylemi yap}; </b> kurtarma bölümünde olası bir atış istisnası ile. Orijinal formülasyonda arama sitesi için <b> deneyin target = (...). ParseInt; catch (...) {do recovery action} </b> ile kurtarma işleminde önemsiz bir fırlatma istisnası, sadece catch cümlesini kaldırarak uygulanır. Önerilen çözüm bunu anlamayı nasıl kolaylaştırır (sihir numarası vardır) veya herhangi bir şekilde kod miktarını azaltır?
Ira Baxter

15
nullReferansları kontrol etmek, istisnaları düzenli olarak ele almaktan daha temizdir .
Adam Maras

Boş değerleri değer olarak iletmekten kaçınmak daha da temizdir, ancak bunun yerine bir şekilde en hatasının oluştuğunu gösterir; istisnalar akış kontrolü için kullanılmamalıdır.
Esko

2
@Steve Kuo: Neden? Fayda nerede? Her ikisi de her seferinde yeni bir Tamsayı mı yaratıyor? Bir şey olursa, Integer.parseInt'i kullanmak ve küçük değerler için önbellekten yararlanmak için otomatik kutunun ilgilenmesine izin vermek istiyorum.
Jon Skeet

1
@Vlasec Ve sadece İsteğe bağlı değil, aynı zamanda OptionalInt gibi ilkeller için özel sürümler.
Joshua Taylor

37

Sayı olmadığında nasıl bir davranış bekliyorsunuz?

Örneğin, genellikle girdi bir sayı olmadığında kullanmak için varsayılan bir değere sahipseniz, bunun gibi bir yöntem yararlı olabilir:

public static int parseWithDefault(String number, int defaultVal) {
  try {
    return Integer.parseInt(number);
  } catch (NumberFormatException e) {
    return defaultVal;
  }
}

Giriş ayrıştırılamadığında, farklı varsayılan davranışlar için benzer yöntemler yazılabilir.


29

Bazı durumlarda ayrıştırma hatalarını başarısız durumlar olarak ele almalısınız, ancak uygulama yapılandırması gibi diğer durumlarda, eksik girdileri Apache Commons Lang 3 NumberUtils kullanarak varsayılan değerlerle işlemeyi tercih ederim .

int port = NumberUtils.toInt(properties.getProperty("port"), 8080);

Çoğu zaman projenizde apache commons'ı başka nedenlerle (StringUtils gibi) kullandığınızda, bu kullanışlı hale gelir.
Ratata Tata

16

İstisnaları işlemekten kaçınmak için önce tüm rakamlara sahip olduğunuzdan emin olmak için normal bir ifade kullanın:

//Checking for Regular expression that matches digits
if(value.matches("\\d+")) {
     Integer.parseInt(value);
}

Cevabınız için teşekkür ederim. Bu sayfadaki cevapların çoğunu okudum, şahsen dene / yakala çözümünü yazdım. ancak işte benim sorunum, küçük de olsa, bu çözümle. çoğu IDE, bir döngü içinde dene / yakala olduğunda kodunuzun akışını analiz ederek boğulacaktır. bu yüzden ihtiyacım olan şey dene / yakala olmadan bir çözümdü.
victor n.

4
Dikkatli ol. Normal ifade, 0 ile başlayan bir tamsayı ile eşleşir ve ardından bir NumberFormatException oluşturur. Bunu deneyin ^ (?: [1-9] \ d * | 0) $ stackoverflow.com/questions/12018479/…
Goose

5
Bu belirli normal ifade, negatif sayıları işlemez.
Brad Cupit

7
bu, tam sayı sınırlarının dışındaki sayı aralıklarını da kapsamaz
Mohammad Yahia

10

Orada Ints.tryParse()içinde Guava . Sayısal olmayan dizge üzerinde istisna atmaz, ancak boş dizge üzerinde istisna atar.


4

Sorunun yanıtlarını okuduktan sonra, parseInt yöntemini özetlemenin ya da paketlemenin gerekli olmadığını, belki de iyi bir fikir olmadığını düşünüyorum.

Jon'un önerdiği gibi 'null' döndürebilirsiniz, ancak bu aşağı yukarı bir dene / yakala yapısını bir boş kontrol ile değiştirmektir. Hata işlemeyi 'unutursanız' davranışta küçük bir fark vardır: istisnayı yakalamazsanız, atama yoktur ve sol taraftaki değişken eski değerini korur. Boş değeri test etmezseniz, muhtemelen JVM (NPE) tarafından vurulacaksınız.

yawn'ın önerisi bana daha zarif görünüyor, çünkü bazı hataları veya istisnai durumları işaret etmek için boş değer döndürmeyi sevmiyorum. Şimdi, önceden tanımlanmış bir nesneyle referans eşitliğini kontrol etmelisiniz, bu bir sorunu gösterir. Ancak, diğerlerinin iddia ettiği gibi, kontrol etmeyi tekrar 'unutursanız' ve bir String ayrıştırılamazsa, program 'ERROR' veya 'NULL' nesnenizin içine sarılmış int ile devam eder.

Nikolay'ın çözümü daha da nesneye yöneliktir ve diğer sarmalayıcı sınıflarından parseXXX yöntemleriyle de çalışacaktır. Ama sonunda, NumberFormatException'ı OperationNotSupported istisnası ile değiştirdi - yeniden ayrıştırılamayan girdileri işlemek için bir dene / yakala ihtiyacın var.

Yani, benim sonucum, düz ayrıştırma yöntemini kapsüllemiyor. Yalnızca bazı (uygulamaya bağlı) hata işlemeyi de ekleyebilseydim kapsülleyebilirdim.


4

Belki bunun gibi bir şey kullanabilirsiniz:

public class Test {
public interface Option<T> {
    T get();

    T getOrElse(T def);

    boolean hasValue();
}

final static class Some<T> implements Option<T> {

    private final T value;

    public Some(T value) {
        this.value = value;
    }

    @Override
    public T get() {
        return value;
    }

    @Override
    public T getOrElse(T def) {
        return value;
    }

    @Override
    public boolean hasValue() {
        return true;
    }
}

final static class None<T> implements Option<T> {

    @Override
    public T get() {
        throw new UnsupportedOperationException();
    }

    @Override
    public T getOrElse(T def) {
        return def;
    }

    @Override
    public boolean hasValue() {
        return false;
    }

}

public static Option<Integer> parseInt(String s) {
    Option<Integer> result = new None<Integer>();
    try {
        Integer value = Integer.parseInt(s);
        result = new Some<Integer>(value);
    } catch (NumberFormatException e) {
    }
    return result;
}

}

Belki modelini kullanarak çözümünüzü beğendim. Çok haskelly;)
rodrigoelp

1
:) Java 8 yana java.util.Optional bulunduğu için, bu çözüm artık modası geçmiş
Vlasec

2

İstediğiniz C ++ davranışını da çok basit bir şekilde çoğaltabilirsiniz.

public static boolean parseInt(String str, int[] byRef) {
    if(byRef==null) return false;
    try {
       byRef[0] = Integer.parseInt(prop);
       return true;
    } catch (NumberFormatException ex) {
       return false;
    }
}

Yöntemi şu şekilde kullanırsınız:

int[] byRef = new int[1];
boolean result = parseInt("123",byRef);

Bundan sonra değişken result, her şey yolunda giderse ve byRef[0]ayrıştırılmış değeri içeriyorsa doğrudur .

Şahsen ben istisnayı yakalamaya devam ederdim.


2

Jon Skeet tarafından verilen cevap güzel, ancak bir nullTamsayı nesnesini geri vermekten hoşlanmıyorum . Bunu kullanmak kafa karıştırıcı buluyorum. Java 8'den beri (bence) daha iyi bir seçenek var OptionalInt:

public static OptionalInt tryParse(String value) {
 try {
     return OptionalInt.of(Integer.parseInt(value));
  } catch (NumberFormatException e) {
     return OptionalInt.empty();
  }
}

Bu, hiçbir değerin mevcut olmadığı durumu halletmeniz gerektiğini açıkça ortaya koyar. Gelecekte bu tür bir işlevin java kitaplığına eklenmesini tercih ederim, ancak bunun gerçekleşip gerçekleşmeyeceğini bilmiyorum.



1

Java'm biraz paslanmış, ancak sizi doğru yöne yönlendirebilecek miyim bir bakalım:

public class Converter {

    public static Integer parseInt(String str) {
        Integer n = null;

        try {
            n = new Integer(Integer.tryParse(str));
        } catch (NumberFormatException ex) {
            // leave n null, the string is invalid
        }

        return n;
    }

}

Dönüş değeriniz ise null, kötü bir değeriniz vardır. Aksi takdirde, geçerli bir hesabınız var Integer.


OP, dönüşüm sonucunu (referans olarak) ve ayrıca dönüşümün başarılı olduğunu (veya olmadığını) belirtmek ister.
esneme

1
@yawn: Ve boş bir referans tam olarak bu göstergeyi verir.
Jon Skeet

@John Skeet: doğru ama amacını farklı okudum. Başarı / başarısızlık + değer arasında ayrım yapmak için bir ara nesne kullanmak gibi bir şey yazdı. C ++ arka planından geldiğimde, null kullanmak isteseydi (bir nesne yerine) soruyu ilk başta sormazdı diye düşündüm.
esneme

"Değer" ve "nesne" arasında büyük bir fark vardır. Boş başvuru temiz bir değerdir, ancak nesne değildir.
Jon Skeet

1. Integer.tryParseStandart Java Integersınıfında yoktur. 2. new IntegerJava otomatik olarak kutulama ve kutudan çıkarma yaptığı için, yapmak gereksizdir (ve buna karşı önerilir). Java'nız sadece biraz paslı değil, çok paslı.
ADTC

1

ParseInt yöntemini çatallamaya ne dersiniz ?

Kolaydır, içeriği kopyalayıp geri döndüren Integerveya geri dönüşlerle Optional<Integer>değiştiren yeni bir yardımcı programa yapıştırın . Görünüşe göre temel kodda istisna yok, ancak daha iyi kontrol edin .

Tüm istisna işleme işlerini atlayarak, geçersiz girişlerde biraz zaman kazanabilirsiniz. Ve yöntem JDK 1.0'dan beri var, bu yüzden onu güncel tutmak için fazla bir şey yapmanız gerekmeyecek.


0

Şöyle bir yöntem düşünmenizi öneririm

 IntegerUtilities.isValidInteger(String s)

daha sonra uygun gördüğünüz şekilde uygularsınız. Sonucun geri taşınmasını istiyorsanız - belki de Integer.parseInt () kullandığınız için - dizi numarasını kullanabilirsiniz.

 IntegerUtilities.isValidInteger(String s, int[] result)

işlemde bulunan tamsayı değerine sonucu [0] olarak ayarlarsınız.


0

Bu biraz Nikolay'ın çözümüne benzer:

 private static class Box<T> {
  T me;
  public Box() {}
  public T get() { return me; }
  public void set(T fromParse) { me = fromParse; }
 }

 private interface Parser<T> {
  public void setExclusion(String regex);
  public boolean isExcluded(String s);
  public T parse(String s);
 }

 public static <T> boolean parser(Box<T> ref, Parser<T> p, String toParse) {
  if (!p.isExcluded(toParse)) {
   ref.set(p.parse(toParse));
   return true;
  } else return false;
 }

 public static void main(String args[]) {
  Box<Integer> a = new Box<Integer>();
  Parser<Integer> intParser = new Parser<Integer>() {
   String myExclusion;
   public void setExclusion(String regex) {
    myExclusion = regex;
   }
   public boolean isExcluded(String s) {
    return s.matches(myExclusion);
   }
   public Integer parse(String s) {
    return new Integer(s);
   }
  };
  intParser.setExclusion("\\D+");
  if (parser(a,intParser,"123")) System.out.println(a.get());
  if (!parser(a,intParser,"abc")) System.out.println("didn't parse "+a.get());
 }

Ana yöntem kodu gösterir. Ayrıştırıcı arabirimini uygulamanın başka bir yolu da, açıkça "\ D +" öğesini yapıdan ayarlamak ve yöntemlerin hiçbir şey yapmamasını sağlamak olacaktır.


0

Sen olabilir rulo kendi, ancak kullanım malı gibi kolay Lang'ın var StringUtils.isNumeric() metod . String'deki her karakter üzerinde yineleme yapmak için Character.isDigit () kullanır .


Bu durumda, rakam çok büyük bir sayı içeriyorsa çalışmayacaktır. Integer.parseInt, Integer.MAX_VALUE değerinden büyük sayılar için bir istisna atar (tabii ki negatif taraf için de aynıdır).
Searles

0

Bu sorunu çözme şeklim özyinelemeli. Örneğin konsoldan veri okurken:

Java.util.Scanner keyboard = new Java.util.Scanner(System.in);

public int GetMyInt(){
    int ret;
    System.out.print("Give me an Int: ");
    try{
        ret = Integer.parseInt(keyboard.NextLine());

    }
    catch(Exception e){
        System.out.println("\nThere was an error try again.\n");
        ret = GetMyInt();
    }
    return ret;
}

0

Bir istisnayı önlemek için Java'nın Format.parseObjectyöntemini kullanabilirsiniz . Aşağıdaki kod temelde Apache Common'un IntegerValidator sınıfının basitleştirilmiş bir sürümüdür .

public static boolean tryParse(String s, int[] result)
{
    NumberFormat format = NumberFormat.getIntegerInstance();
    ParsePosition position = new ParsePosition(0);
    Object parsedValue = format.parseObject(s, position);

    if (position.getErrorIndex() > -1)
    {
        return false;
    }

    if (position.getIndex() < s.length())
    {
        return false;
    }

    result[0] = ((Long) parsedValue).intValue();
    return true;
}

Tercihinize bağlı olarak AtomicIntegerya da int[]dizi numarasını kullanabilirsiniz .

İşte onu kullanan testim -

int[] i = new int[1];
Assert.assertTrue(IntUtils.tryParse("123", i));
Assert.assertEquals(123, i[0]);

0

Ben de aynı sorunu yaşıyordum. Bu, kullanıcıdan bir girdi istemek ve bir tamsayı olmadıkça girdiyi kabul etmemek için yazdığım bir yöntem. Lütfen yeni başlayan olduğumu unutmayın, bu nedenle kod beklendiği gibi çalışmıyorsa, deneyimsizliğimi suçlayın!

private int numberValue(String value, boolean val) throws IOException {
    //prints the value passed by the code implementer
    System.out.println(value);
    //returns 0 is val is passed as false
    Object num = 0;
    while (val) {
        num = br.readLine();
        try {
            Integer numVal = Integer.parseInt((String) num);
            if (numVal instanceof Integer) {
                val = false;
                num = numVal;
            }
        } catch (Exception e) {
            System.out.println("Error. Please input a valid number :-");
        }
    }
    return ((Integer) num).intValue();
}

1
System.out.println kullanmayın (kötü bir uygulamadır). Kullanmakla ilgili sorun, programınızın println bitene kadar bekleyecek olmasıdır. Daha iyi bir yaklaşım, bir günlükleme çerçevesi kullanmaktır.
Omar Hrynkiewicz

0

Bu 8391979 numaralı sorunun cevabıdır, "Java'nın kötü veriler için bir istisna oluşturmayan bir int.tryparse var mı? [Yinelenen]" kapalı ve bu soruya bağlı.

Edit 2016 08 17: ltrimZeroes yöntemleri eklendi ve bunları tryParse () 'da çağırdı. NumberString'in başında sıfır olmadan yanlış sonuçlar verebilir (koddaki yorumlara bakın). Artık pozitif ve negatif "sayılar" (END Edit) için çalışan genel statik String ltrimZeroes (String numberString) yöntemi de var

Aşağıda, dizenin kendisini ayrıştıran ve Java'daki Integer.parseInt (String s) 'den biraz daha hızlı olan, yüksek hızda optimize edilmiş tryParse () yöntemine (C # ile benzer) sahip int için temel bir Wrapper (boxing) sınıfı bulacaksınız:

public class IntBoxSimple {
    // IntBoxSimple - Rudimentary class to implement a C#-like tryParse() method for int
    // A full blown IntBox class implementation can be found in my Github project
    // Copyright (c) 2016, Peter Sulzer, Fürth
    // Program is published under the GNU General Public License (GPL) Version 1 or newer

    protected int _n; // this "boxes" the int value

    // BEGIN The following statements are only executed at the
    // first instantiation of an IntBox (i. e. only once) or
    // already compiled into the code at compile time:
    public static final int MAX_INT_LEN =
            String.valueOf(Integer.MAX_VALUE).length();
    public static final int MIN_INT_LEN =
            String.valueOf(Integer.MIN_VALUE).length();
    public static final int MAX_INT_LASTDEC =
            Integer.parseInt(String.valueOf(Integer.MAX_VALUE).substring(1));
    public static final int MAX_INT_FIRSTDIGIT =
            Integer.parseInt(String.valueOf(Integer.MAX_VALUE).substring(0, 1));
    public static final int MIN_INT_LASTDEC =
            -Integer.parseInt(String.valueOf(Integer.MIN_VALUE).substring(2));
    public static final int MIN_INT_FIRSTDIGIT =
            Integer.parseInt(String.valueOf(Integer.MIN_VALUE).substring(1,2));
    // END The following statements...

    // ltrimZeroes() methods added 2016 08 16 (are required by tryParse() methods)
    public static String ltrimZeroes(String s) {
        if (s.charAt(0) == '-')
            return ltrimZeroesNegative(s);
        else
            return ltrimZeroesPositive(s);
    }
    protected static String ltrimZeroesNegative(String s) {
        int i=1;
        for ( ; s.charAt(i) == '0'; i++);
        return ("-"+s.substring(i));
    }
    protected static String ltrimZeroesPositive(String s) {
        int i=0;
        for ( ; s.charAt(i) == '0'; i++);
        return (s.substring(i));
    }

    public static boolean tryParse(String s,IntBoxSimple intBox) {
        if (intBox == null)
            // intBoxSimple=new IntBoxSimple(); // This doesn't work, as
            // intBoxSimple itself is passed by value and cannot changed
            // for the caller. I. e. "out"-arguments of C# cannot be simulated in Java.
            return false; // so we simply return false
        s=s.trim(); // leading and trailing whitespace is allowed for String s
        int len=s.length();
        int rslt=0, d, dfirst=0, i, j;
        char c=s.charAt(0);
        if (c == '-') {
            if (len > MIN_INT_LEN) { // corrected (added) 2016 08 17
                s = ltrimZeroesNegative(s);
                len = s.length();
            }
            if (len >= MIN_INT_LEN) {
                c = s.charAt(1);
                if (!Character.isDigit(c))
                    return false;
                dfirst = c-'0';
                if (len > MIN_INT_LEN || dfirst > MIN_INT_FIRSTDIGIT)
                    return false;
            }
            for (i = len - 1, j = 1; i >= 2; --i, j *= 10) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt -= (c-'0')*j;
            }
            if (len < MIN_INT_LEN) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt -= (c-'0')*j;
            } else {
                if (dfirst >= MIN_INT_FIRSTDIGIT && rslt < MIN_INT_LASTDEC)
                    return false;
                rslt -= dfirst * j;
            }
        } else {
            if (len > MAX_INT_LEN) { // corrected (added) 2016 08 16
                s = ltrimZeroesPositive(s);
                len=s.length();
            }
            if (len >= MAX_INT_LEN) {
                c = s.charAt(0);
                if (!Character.isDigit(c))
                    return false;
                dfirst = c-'0';
                if (len > MAX_INT_LEN || dfirst > MAX_INT_FIRSTDIGIT)
                    return false;
            }
            for (i = len - 1, j = 1; i >= 1; --i, j *= 10) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt += (c-'0')*j;
            }
            if (len < MAX_INT_LEN) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt += (c-'0')*j;
            }
            if (dfirst >= MAX_INT_FIRSTDIGIT && rslt > MAX_INT_LASTDEC)
                return false;
            rslt += dfirst*j;
        }
        intBox._n=rslt;
        return true;
    }

    // Get the value stored in an IntBoxSimple:
    public int get_n() {
        return _n;
    }
    public int v() { // alternative shorter version, v for "value"
        return _n;
    }
    // Make objects of IntBoxSimple (needed as constructors are not public):
    public static IntBoxSimple makeIntBoxSimple() {
        return new IntBoxSimple();
    }
    public static IntBoxSimple makeIntBoxSimple(int integerNumber) {
        return new IntBoxSimple(integerNumber);
    }

    // constructors are not public(!=:
    protected IntBoxSimple() {} {
        _n=0; // default value an IntBoxSimple holds
    }
    protected IntBoxSimple(int integerNumber) {
        _n=integerNumber;
    }
}

IntBoxSimple sınıfı için test / örnek program:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class IntBoxSimpleTest {
    public static void main (String args[]) {
        IntBoxSimple ibs = IntBoxSimple.makeIntBoxSimple();
        String in = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        do {
            System.out.printf(
                    "Enter an integer number in the range %d to %d:%n",
                        Integer.MIN_VALUE, Integer.MAX_VALUE);
            try { in = br.readLine(); } catch (IOException ex) {}
        } while(! IntBoxSimple.tryParse(in, ibs));
        System.out.printf("The number you have entered was: %d%n", ibs.v());
    }
}

0

Normal ifade ve varsayılan parametreler bağımsız değişkeniyle deneyin

public static int parseIntWithDefault(String str, int defaultInt) {
    return str.matches("-?\\d+") ? Integer.parseInt(str) : defaultInt;
}


int testId = parseIntWithDefault("1001", 0);
System.out.print(testId); // 1001

int testId = parseIntWithDefault("test1001", 0);
System.out.print(testId); // 1001

int testId = parseIntWithDefault("-1001", 0);
System.out.print(testId); // -1001

int testId = parseIntWithDefault("test", 0);
System.out.print(testId); // 0

apache.commons.lang3 kullanıyorsanız NumberUtils'i kullanarak :

int testId = NumberUtils.toInt("test", 0);
System.out.print(testId); // 0

0

Biri özellikle tamsayılar isterse işe yarayan başka bir öneri eklemek istiyorum: Hata durumları için long ve Long.MIN_VALUE kullanın. Bu, Reader'da karakterler için kullanılan yaklaşıma benzerdir; burada Reader.read (), bir karakter aralığında bir tamsayı veya okuyucu boşsa -1 döndürür.

Float ve Double için NaN benzer şekilde kullanılabilir.

public static long parseInteger(String s) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        return Long.MIN_VALUE;
    }
}


// ...
long l = parseInteger("ABC");
if (l == Long.MIN_VALUE) {
    // ... error
} else {
    int i = (int) l;
}

0

Mevcut cevapları göz önünde bulundurarak Integer.parseInt, işi yapmak için kopyalayıp yapıştırdım ve geliştirdim kaynak kodu ve çözümüm

  • potansiyel olarak yavaş deneme yakalama kullanmaz ( Lang 3 NumberUtils'in aksine ),
  • çok büyük sayıları yakalayamayan normal ifadeler kullanmaz,
  • boks yapmaktan kaçınır (Guava'nın aksine Ints.tryParse()),
  • (aksine ayırmadığı gerektirmez int[], Box, OptionalInt),
  • CharSequencebir bütün yerine bir kısmını veya bir kısmını kabul eden String,
  • herhangi bir taban Integer.parseIntkullanabilir, yani [2,36],
  • herhangi bir kütüphaneye bağlı değildir.

Tek dezavantajı, toIntOfDefault("-1", -1)ve arasında hiçbir fark olmamasıdır toIntOrDefault("oops", -1).

public static int toIntOrDefault(CharSequence s, int def) {
    return toIntOrDefault0(s, 0, s.length(), 10, def);
}
public static int toIntOrDefault(CharSequence s, int def, int radix) {
    radixCheck(radix);
    return toIntOrDefault0(s, 0, s.length(), radix, def);
}
public static int toIntOrDefault(CharSequence s, int start, int endExclusive, int def) {
    boundsCheck(start, endExclusive, s.length());
    return toIntOrDefault0(s, start, endExclusive, 10, def);
}
public static int toIntOrDefault(CharSequence s, int start, int endExclusive, int radix, int def) {
    radixCheck(radix);
    boundsCheck(start, endExclusive, s.length());
    return toIntOrDefault0(s, start, endExclusive, radix, def);
}
private static int toIntOrDefault0(CharSequence s, int start, int endExclusive, int radix, int def) {
    if (start == endExclusive) return def; // empty

    boolean negative = false;
    int limit = -Integer.MAX_VALUE;

    char firstChar = s.charAt(start);
    if (firstChar < '0') { // Possible leading "+" or "-"
        if (firstChar == '-') {
            negative = true;
            limit = Integer.MIN_VALUE;
        } else if (firstChar != '+') {
            return def;
        }

        start++;
        // Cannot have lone "+" or "-"
        if (start == endExclusive) return def;
    }
    int multmin = limit / radix;
    int result = 0;
    while (start < endExclusive) {
        // Accumulating negatively avoids surprises near MAX_VALUE
        int digit = Character.digit(s.charAt(start++), radix);
        if (digit < 0 || result < multmin) return def;
        result *= radix;
        if (result < limit + digit) return def;
        result -= digit;
    }
    return negative ? result : -result;
}
private static void radixCheck(int radix) {
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        throw new NumberFormatException(
                "radix=" + radix + " ∉ [" +  Character.MIN_RADIX + "," + Character.MAX_RADIX + "]");
}
private static void boundsCheck(int start, int endExclusive, int len) {
    if (start < 0 || start > len || start > endExclusive)
        throw new IndexOutOfBoundsException("start=" + start + " ∉ [0, min(" + len + ", " + endExclusive + ")]");
    if (endExclusive > len)
        throw new IndexOutOfBoundsException("endExclusive=" + endExclusive + " > s.length=" + len);
}

0

Belki birisi daha genel bir yaklaşım arıyor, çünkü Java 8 java.util.functionTedarikçi İşlevlerini tanımlamaya izin veren bir Paket var. Aşağıdaki gibi bir tedarikçiyi ve varsayılan bir değeri alan bir işleve sahip olabilirsiniz:

public static <T> T tryGetOrDefault(Supplier<T> supplier, T defaultValue) {
    try {
        return supplier.get();
    } catch (Exception e) {
        return defaultValue;
    }
}

Bu işlevle, herhangi bir ayrıştırma yöntemini veya bir İstisna atabilecek diğer yöntemleri çalıştırabilirken, hiçbir İstisnanın atılmamasını sağlayabilirsiniz:

Integer i = tryGetOrDefault(() -> Integer.parseInt(stringValue), 0);
Long l = tryGetOrDefault(() -> Long.parseLong(stringValue), 0l);
Double d = tryGetOrDefault(() -> Double.parseDouble(stringValue), 0d);

-1

Null-Object'i şöyle kullanabilirsiniz:

public class Convert {

    @SuppressWarnings({"UnnecessaryBoxing"})
    public static final Integer NULL = new Integer(0);

    public static Integer convert(String integer) {

        try {
            return Integer.valueOf(integer);
        } catch (NumberFormatException e) {
            return NULL;
        }

    }

    public static void main(String[] args) {

        Integer a = convert("123");
        System.out.println("a.equals(123) = " + a.equals(123));
        System.out.println("a == NULL " + (a == NULL));

        Integer b = convert("onetwothree");
        System.out.println("b.equals(123) = " + b.equals(123));
        System.out.println("b == NULL " + (b == NULL));

        Integer c = convert("0");
        System.out.println("equals(0) = " + c.equals(0));
        System.out.println("c == NULL " + (c == NULL));

    }

}

Bu örnekte main'in sonucu :

a.equals(123) = true
a == NULL false
b.equals(123) = false
b == NULL true
c.equals(0) = true
c == NULL false

Bu şekilde, her zaman başarısız dönüşümü test edebilir, ancak yine de sonuçlarla Tamsayı örnekleri olarak çalışabilirsiniz. Ayrıca NULL'un temsil ettiği sayıyı (≠ 0) değiştirmek isteyebilirsiniz .


Ya 'Dize tamsayı' String değişmez değeri "0" ise? Geçersiz giriş olup olmadığını asla bilemezsiniz.
Bart Kiers

Sanırım bu, iki Tamsayı için == operatörünün değerleri veya başvuruları karşılaştırıp karşılaştırmamasına bağlı. Değerleri karşılaştırırsa sorun vardır. Referansları karşılaştırırsa, cevabıma eşdeğer bir şekilde çalışacaktır.
Adam Maras

Neden olumsuz oy? Cevabım doğrudur ve sizi NPE'lerle uğraşmak zorunda bırakmadan her zaman geçerli bir Tamsayı örneğiyle (boş yerine) uğraşmanız avantajını (boşa göre) sunar.
esneme

Null değerini gerçek tam sayıdan ayırmak yararlıdır . Sen olmalıdır ayrıştırma başarılı olup olmadığını bilmek, butlan sonucunu test etmek. Bunu arkasına ve başka şekilde kullanılabilir nesneyi saklamak, problemler için bir reçetedir, IMO.
Jon Skeet

Daha fazla olumsuz oy - ilginç! SO'da yeni olduğum için ve seçmenlerden biri bana nedenini açıklayabilir mi?
esneme

-1

Değerlerinizi doğrulamak için İstisnalar kullanmamalısınız .

Tek karakter için basit bir çözüm var:

Character.isDigit()

Daha uzun değerler için bazı araçlar kullanmak daha iyidir. Apache tarafından sağlanan NumberUtils burada mükemmel çalışır:

NumberUtils.isNumber()

Lütfen https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/math/NumberUtils.html adresini kontrol edin.


«Dizenin geçerli bir Java numarası olup olmadığını kontrol eder. Geçerli sayılar, 0x niteleyicisi ile işaretlenmiş onaltılık tabanda, bilimsel gösterim ve bir tür niteleyicisi ile işaretlenmiş sayıları (ör. 123L) içerir. » Bu, çözümlenebilecek şey değil Integer.parseInt.
Miha_x64
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.