Integer.parseInt()をカプセル化する良い方法


88

Integer.parseInt()Stringをintに変換するためによく使用するプロジェクトがあります。何かがうまくいかない場合(たとえば、はString数字ではなく文字a、など)、このメソッドは例外をスローします。ただし、コード内のどこでも例外を処理する必要がある場合、これは非常に醜く非常にすぐに見え始めます。これをメソッドに入れたいのですが、変換が失敗したことを示すためにクリーンな値を返す方法がわかりません。

C ++では、intへのポインターを受け入れるメソッドを作成し、メソッド自体にtrueまたはfalseを返させることができます。ただし、私の知る限り、これはJavaでは不可能です。true / false変数と変換された値を含むオブジェクトを作成することもできますが、これも理想的ではないようです。同じことがグローバルな値にも当てはまり、マルチスレッドで問題が発生する可能性があります。

これを行うクリーンな方法はありますか?


文字列内の文字は、最初の文字...を除き、すべて10進数でなければなりません。コードのあらゆる場所で例外を処理する代わりに、解析メソッドを呼び出す前に文字列形式を確認するだけです。
Lightman、

すべての有効な32ビット符号付き整数をキャプチャし、無効な整数をキャプチャしない正規表現を書くのはほとんど不可能です。2147483647は合法ですが、int2147483648はそうではありません。
Seva Alekseyev

回答:


139

Integer代わりにを返すことができ、解析の失敗時intに戻りnullます。

内部で例外がスローされない限り、Javaがこれを行う方法を提供しないのは残念です。例外をキャッチしてnullを返すことにより、例外を隠すことができますが、何百ものパースを実行している場合でも、パフォーマンスの問題になる可能性があります。数千ビットのユーザー提供データ。

編集:そのようなメソッドのコード:

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

textがnullの場合、これがどうなるかは頭の上ではわかりません。あなたはそれを考慮すべきです-それがバグを表すなら(つまり、あなたのコードは無効な値を渡すかもしれませんが、nullを渡すべきではありません)例外を投げることは適切です; バグを表していない場合は、他の無効な値の場合と同様に、おそらくnullを返す必要があります。

もともとこの回答はnew Integer(String)コンストラクタを使用していました。現在はInteger.parseIntボクシング操作を使用しています。このようにして、小さな値はキャッシュされたIntegerオブジェクトにボックス化され、それらの状況でより効率的になります。


1
これはどのように役立ちますか?呼び出しサイトには以下が必要です。<b> temp = tryParse(...); if(temp!= Null){target = temp; } else {回復アクションを実行する}; </ b>回復部分でスロー例外が発生する可能性があります。元の式では、呼び出しサイトには<b> try target =(...)。parseInt;が必要です。catch(...){doリカバリーアクション} </ b>は、catch句を削除するだけで実装されるリカバリーで、簡単なスロー例外を実装します。提案されたソリューションは、これをどのように理解しやすくするか(手品を備えています)、またはコードの量を何らかの方法で削減しますか?
Ira Baxter

14
null通常、例外を定期的に処理するよりも、参照をチェックするコードを記述した方がクリーンです。
Adam Maras

nullを値として渡さないようにする方がすっきりしていますが、エラーが発生したことを何らかの形で示しています。フロー制御には例外を使用しないでください。
Esko、

2
@Steve Kuo:なぜ?メリットはどこですか?彼らは両方とも毎回新しい整数を作成しますか?どちらかといえば、私はInteger.parseIntを使用して、小さな値のキャッシュを利用するためにオートボクシングにそれを処理させたいと思っています。
Jon Skeet

1
@Vlasecそして、Optionalだけでなく、OptionalIntのようなプリミティブの専用バージョン。
ジョシュアテイラー

36

数値でない場合、どのような動作を期待しますか?

たとえば、入力が数値でないときに使用するデフォルト値がよくある場合、次のような方法が役立ちます。

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

入力を解析できない場合、同様のメソッドをさまざまなデフォルトの動作に対して作成できます。


29

場合によっては、解析エラーをフェイルファストの状況として処理する必要がありますが、アプリケーション構成などの他の場合では、Apache Commons Lang 3 NumberUtilsを使用して、デフォルト値で欠落した入力を処理することを好みます。

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

ほとんどの場合、他の理由(StringUtilsなど)が原因で、プロジェクトですでにApache Commonsを使用しているため、便利です。
Ratata Tata 2017

17

例外の処理を回避するには、正規表現を使用して、最初にすべての数字があることを確認します。

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

お返事ありがとうございます。私はこのページのほとんどの回答を読みましたが、私は個人的にtry / catchソリューションを作成していました。しかし、ここではその解決策についての小さな問題です。ほとんどのIDEは、ループの内側にtry / catchがあると、コードのフローを分析するのを妨げます。そのため、try / catchを使用しないソリューションが必要でした。
勝利者n。

4
注意してください。の正規表現は、0で始まる整数と一致し、NumberFormatExceptionをスローします。この^(?:[1-9] \ d * | 0)$をお試しください。stackoverflow.com/ questions / 12018479
Goose

4
この特定の正規表現は負の数を処理しません。
Brad Cupit 2016年

6
また、これは整数の範囲外の数値範囲をカバーしていません
Mohammad Yahia

10

ありInts.tryParse()グアバ。数値以外の文字列では例外をスローしませんが、null文字列では例外をスローします。


4

質問への回答を読んだ後、parseIntメソッドをカプセル化またはラップする必要はないと思います。

Jonが提案したように「null」を返すこともできますが、それは多かれ少なかれ、try / catch構成をnullチェックに置き換えます。エラー処理を「忘れた」場合の動作にはわずかな違いがあります。例外をキャッチしない場合、代入は行われず、左側の変数が古い値を保持します。nullをテストしないと、おそらくJVM(NPE)に見舞われるでしょう。

いくつかのエラーや例外的な状態を示すためにnullを返すのは好きではないので、あくびの提案は私にはよりエレガントに見えます。次に、事前定義されたオブジェクトとの参照の等価性をチェックする必要があります。これは問題を示しています。しかし、他の人が主張するように、もう一度確認するのを「忘れて」、文字列が解析できない場合、プログラムは「ERROR」または「NULL」オブジェクト内のラップされたintで継続します。

Nikolayのソリューションはさらにオブジェクト指向であり、他のラッパークラスのparseXXXメソッドでも機能します。しかし、結局、彼はNumberFormatExceptionをOperationNotSupported例外に置き換えただけです。ここでも、解析不可能な入力を処理するためにtry / catchが必要です。

つまり、プレーンなparseIntメソッドをカプセル化しないという私の結論です。(アプリケーションに依存する)エラー処理も追加できる場合のみカプセル化します。


4

あなたはこのようなものを使うことができるかもしれません:

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;
}

}

多分パターンを使用したソリューションが好きです。非常にhaskelly;)
rodrigoelp 2013年

1
Java 8以降、java.util.Optionalがあるため、このソリューションは古くなっています:)
Vlasec

2

非常に簡単にしたいC ++の動作を複製することもできます

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;
    }
}

次のような方法を使用します。

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

その後、変数はresultすべてが問題なく行わbyRef[0]れ、解析された値を含んでいる場合にtrueになります。

個人的には、例外をキャッチすることに固執します。


2

Jon Skeetの答えは結構ですが、nullIntegerオブジェクトを返すのは好きではありません。これは使用するのが難しいと思います。Java 8以来、(私の意見では)より良いオプションがありますOptionalInt

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

これにより、値が利用できない場合に対処する必要があることが明確になります。この種の関数が将来的にJavaライブラリに追加されることを望みますが、それが実現するかどうかはわかりません。


2

Java 8以降を使用している場合は、先ほどリリースしたライブラリhttps://github.com/robtimus/try-parseを使用できます。例外のキャッチに依存しないint、long、booleanをサポートしています。GuavaのInts.tryParseとは異なり、https: //stackoverflow.com/a/38451745/1180351とよく似ていますが、より効率的なOptionalInt / OptionalLong / Optionalを返します。


1

私のJavaは少し錆びていますが、正しい方向に向けることができるかどうかを見てみましょう。

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;
    }

}

戻り値がのnull場合は、不正な値です。それ以外の場合は、有効ながありますInteger


OPは、変換結果(参照として)に加えて、変換が成功した(または失敗した)ことを示します。
あくび

1
@yawn:そしてnull参照はまさにその指示を与えます。
Jon Skeet

@ジョン・スキート:正解ですが、私は彼の意図を別の方法で読みました。彼は中間オブジェクトを使用して成功/失敗+値を区別するようなものを書きました。C ++の背景から来たので、(オブジェクトの代わりに)nullを使用したいのであれば、そもそも質問をしなかったでしょう。
あくび

「値」と「オブジェクト」の間には大きな違いがあります。null参照はクリーンな値ですが、オブジェクトではありません。
Jon Skeet

1. Integer.tryParse標準のJava Integerクラスにはありません。2. new IntegerJavaは自動的にボックス化とボックス化解除を行うため、実行する必要はありません(推奨されません)。あなたのJavaは少し錆びているだけでなく、とても錆びています。
ADTC

1

parseIntメソッドのフォークについてはどうですか?

簡単です。コンテンツをコピーするIntegerOptional<Integer>、またはスローをリターンに置き換える新しいユーティリティにコピーアンドペーストするだけです。基礎となるコードに例外はないようですが、チェックすることをお勧めしますます。

例外処理をすべてスキップすることで、無効な入力の時間を節約できます。また、このメソッドはJDK 1.0以降に存在するため、最新の状態に保つために多くのことを行う必要はありません。


0

次のような方法を検討することをお勧めします

 IntegerUtilities.isValidInteger(String s)

次に、必要に応じて実装します。結果を持ち帰りたい場合-おそらくとにかくInteger.parseInt()を使用しているため-配列トリックを使用できます。

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

ここで、result [0]をプロセスで見つかった整数値に設定します。


0

これは、ニコライのソリューションにいくぶん似ています。

 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());
 }

mainメソッドはコードをデモします。パーサーインターフェイスを実装する別の方法は、「\ D +」を構築から設定し、メソッドが何もしないようにすることです。


0

自分でロールすることもできますが、commons langのStringUtils.isNumeric() メソッドを使用するのと同じくらい簡単です。これは、Character.isDigit()を使用して、文字列内の各文字を繰り返し処理します。


その場合、数字に含まれている数値が大きすぎると機能しません。Integer.parseIntは、Integer.MAX_VALUEより大きい数値に対して例外をスローします(もちろん、負の側も同じです)。
Searles 2018

0

彼らが私がこの問題を処理する方法は再帰的です。たとえば、コンソールからデータを読み取る場合:

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

例外を回避するには、JavaのFormat.parseObjectメソッドを使用できます。以下のコードは、基本的にはApache CommonのIntegerValidatorクラスの簡略化されたバージョンです。

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;
}

好みに応じて、AtomicIntegerまたはint[]配列トリックを使用できます。

これがそれを使用する私のテストです-

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

0

私も同じ問題を抱えていました。これは、ユーザーに入力を要求し、整数でない限り入力を受け入れないように書いた方法です。私は初心者なので、コードが期待どおりに機能しない場合は、私の経験不足を非難してください!

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は使用しないでください(悪い習慣です)。これを使用する際の問題は、プログラムがprintlnが終了するまで待機することです。優れたアプローチは、ロギングフレームワークを使用することです。
Omar Hrynkiewicz

0

これは、質問8391979への回答です。「Javaには、不正なデータの例外をスローしないint.tryparseがありますか?[重複]」と閉じ、この質問にリンクしています。

Edit 2016 08 17:ltrimZeroesメソッドを追加し、tryParse()で呼び出しました。numberStringに先行ゼロがないと、誤った結果が生じる可能性があります(コード内のコメントを参照)。現在、正および負の「数値」で機能するパブリック静的String ltrimZeroes(String numberString)メソッドもあります(END編集)

以下は、文字列自体を解析し、JavaのInteger.parseInt(String s)よりも少し高速である、非常に高速に最適化されたtryParse()メソッド(C#と同様)を備えたintの基本的なラッパー(ボクシング)クラスを示しています。

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のテスト/サンプルプログラム:

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

正規表現とデフォルトのパラメータ引数で試してください

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を使用している場合は、NumberUtilsを使用します

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

0

特に整数を要求する場合に機能する別の提案を提出したいと思います。単にlongを使用し、エラーの場合はLong.MIN_VALUEを使用します。これは、Readerの文字に使用されるアプローチに似ています。Reader.read()は、charの範囲の整数を返すか、リーダーが空の場合は-1を返します。

FloatとDoubleの場合、NaNは同様の方法で使用できます。

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

既存の回答を考慮して、私はInteger.parseInt仕事をするためにコピーして貼り付けて拡張したソースコードと私の解決策を持っています

  • 潜在的に遅いtry-catchを使用しません(Lang 3 NumberUtilsとは異なります))、
  • 大きすぎる数をキャッチできない正規表現を使用しない、
  • ボクシングを避けます(グアバのとは異なり Ints.tryParse())、
  • 違って(任意の割り当てを必要としませんint[]BoxOptionalInt)、
  • CharSequence全体ではなく、その一部または一部を受け入れるString
  • 基数を使用できます Integer.parseInt。つまり、[2,36]、
  • ライブラリに依存しません。

唯一の欠点は、間に違いありませんということであるtoIntOfDefault("-1", -1)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);
}

-1

次のようにNullオブジェクトを使用できます。

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));

    }

}

この例のmainの結果は次のとおりです。

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

このようにして、失敗した変換を常にテストしながら、結果を整数インスタンスとして操作できます。NULLが表す数(≠0)を調整することもできます


「文字列整数」が文字列リテラル「0」の場合はどうなりますか?無効な入力があったかどうかは決してわかりません。
Bart Kiers、2009

これは、2つの整数の==演算子が値または参照を比較するかどうかに依存すると思います。値を比較する場合、問題が存在します。参照を比較すると、私の答えと同じように機能します。
Adam Maras

なぜ反対票か。私の答えは正解であり、(nullではなく)Integerの有効なインスタンスを常に処理するという利点(nullよりも)を提供し、NPEを処理する必要をなくします。
あくび

ただし、nullを実際の整数と区別することは有用です。解析が成功したかどうかを確認するには、結果がnullかどうかをテストする必要があります。IMOは、その背後にあるオブジェクトとそれ以外の点で使用可能なオブジェクトを非表示にすることは、問題のレシピです。
Jon Skeet

より多くの反対票-興味深い!/ meはSOにとって新しいものであり、有権者の1人がその理由を私に説明できますか?
あくび

-1

値を検証するために例外を使用しないでください

単一の文字の場合、簡単な解決策があります:

Character.isDigit()

値が長い場合は、いくつかのユーティリティを使用することをお勧めします。Apacheが提供するNumberUtilsは、ここで完全に機能します。

NumberUtils.isNumber()

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/math/NumberUtils.htmlを確認してください


≪文字列が有効なJava番号かどうかを確認します。有効な数値には、0x修飾子でマークされた16進数、科学表記法、および型修飾子でマークされた数字(123Lなど)が含まれます。» これはで解析できるものではありませんInteger.parseInt
Miha_x64
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.