web-dev-qa-db-ja.com

DecimalFormatを使用した書式設定は例外をスローします-「指定されたオブジェクトを数値として書式設定できません」

これは繰り返される質問のように見えるかもしれませんが、以下のすべてのリンクを試してみましたが、適切な答えを得ることができません。

指定されたオブジェクトを数値コンボボックスとしてフォーマットできません

不正な引数の例外

しかし、私は何が悪いのかわかりません。ここに私のコードがあります

DecimalFormat twoDForm = new DecimalFormat("#.##");
double externalmark = 1.86;
double internalmark = 4.0;
System.out.println(String.valueOf((externalmark*3+internalmark*1)/4));
String val = String.valueOf((externalmark*3+internalmark*1)/4);
String wgpa1=twoDForm.format(val); // gives exception
String wgpa2=twoDForm.format((externalmark*3+internalmark*1)/4)); // works fine
System.out.println(wgpa1);

formatメソッドはObject型の引数を取るため、例外を与えるStringオブジェクトを渡しました。

スレッド「main」の例外Java.lang.IllegalArgumentException:Cannot指定されたオブジェクトを数値としてフォーマットする。

しかし、引数としてdouble値を指定すると、プログラムは正常に動作します。しかし、メソッドがObject型引数で定義されている場合、Stringを渡すときに例外が発生し、doubleを渡すときに例外が発生しないのはなぜですか?

9
Arun Sudhakaran

DecimalFormatformat()メソッドはオーバーロードされています。

作業ケースでは、呼び出しています:

 public final String format(double number)

そして失敗した場合、あなたは呼び出しています:

 public final String format (Object obj) 

最初のメソッドは非常に具体的な引数を取ります。 doubleが必要です。

これは2番目の場合には当てはまりません。受け入れられる型は非常に広く、Objectです。そこで、渡された型のチェックは実行時に実行されます。

doubleではなくStringではない引数を指定すると、呼び出されるメソッドは2番目のメソッドになります。

内部では、このメソッドは、numberクラス(NumberShort、... Long)のインスタンスであるDouble引数を想定するformat(Object number, StringBuffer toAppendTo, FieldPosition pos)メソッドに依存しています。

@Override
public final StringBuffer format(Object number,
                                 StringBuffer toAppendTo,
                                 FieldPosition pos) {
    if (number instanceof Long || 
        number instanceof Integer ||                   
        number instanceof Short || 
        number instanceof Byte ||                   
        number instanceof AtomicInteger ||
        number instanceof AtomicLong ||
        (number instanceof BigInteger && ((BigInteger)number).bitLength () < 64)) {

        return format(((Number)number).longValue(), toAppendTo, pos);
    } else if (number instanceof BigDecimal) {
        return format((BigDecimal)number, toAppendTo, pos);
    } else if (number instanceof BigInteger) {
        return format((BigInteger)number, toAppendTo, pos);
    } else if (number instanceof Number) {
        return format(((Number)number).doubleValue(), toAppendTo, pos);
    } else {
        throw new IllegalArgumentException("Cannot format given Object as a Number");
    }
}

ただし、Stringインスタンスを渡した場合はそうではありません。

問題を解決するには、成功の場合のようにdoubleプリミティブを渡すか、StringDouble.valueOf(yourString)NumberなどのDoubleのインスタンスに変換します。
最初の方法(doubleを渡す)は、既にdoubleプリミティブを使用しているコードではより自然であるため、お勧めします。
2番目のメソッドでは、StringからDoubleへの追加の変換操作が必要です。

14
davidxxx

答えは javadoc にあります。 「数値はNumberの任意のサブクラスのものである可能性があります」と明確に示され、「数値がnullの場合またはNumberのインスタンスではない場合」IllegalArgumentExceptionをスローします。

(それでは、なぜパラメータをNumber型にしないのですか?クラスは抽象クラスのサブクラスであるためです Format 数値に制限されないクラス明らかに、一般的なFormatクラスにはObjectパラメータを持つメソッドがありますが、Formatのサブクラスはパラメータをオブジェクト型に制限することが期待されているようです。実行時に処理する必要がある処理)

1
ajb