きっかけ
プログラミングが得意ではなかった1年生が4年後にTAをやるなんて思いもしなかった...(遠い目)
僕はTAでレポートの仮採点をしています。その時の質問をネタにしました。
parseDoubleメソッドにはthrowが1つしかないのに、APIには2つあるのはなんで?
JavaにはparseDoubleというメソッドがあります。このメソッドは、変換可能であればString型の文字列をDobule型の数値に変換することができます。
さて、APIを見てみるとこんなことが書いてあります。
NullPointerException
- if the string is nullNumberFormatException
- if the string does not contain a parsable double
.
どこが問題かと言うと、parseDoubleは最初に、
public static double parseDouble(String s)
throws NumberFormatException
と書いているのです。
NumberFormatExceptionはthrowで明示されているのに、NullPointerExceptionはどこでthrowされているのでしょう?
これを調べるにはJDKの実装を見てみるのが早いと思いました。
public static double parseDouble(String s) throws NumberFormatException {
return FloatingDecimal.parseDouble(s);
}
どうやらFloatingDecimalに処理を投げているようです。
FloatingDecimalを読んでみると、109行目にparseDoubleがあります。
public static double parseDouble(String s) throws NumberFormatException {
return readJavaFormatString(s).doubleValue();
}
どうやらreadJavaFormatStringに処理をなげ(ry
同じクラスの中にあるようです。1830行目にありました。
static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
boolean isNegative = false;
boolean signSeen = false;
int decExp;
char c;
parseNumber:
try{
in = in.trim(); // don't fool around with white space.
// throws NullPointerException if null
int len = in.length();
if ( len == 0 ) {
throw new NumberFormatException("empty String");
}
ここで注目なのはin = in.trim()です。コメントにthrows NullPointerException if nullとあります。inはString型のフィールドです。どうやらinがnullの時、trimをするとNullPointerExceptionが投げられるようです。どういう仕組みでしょうか?(まあ、ここで調査を打ち切ってもいいのですが、納得するまで続けます。)
trimはStringクラスにあります。2867行目にあります。
public String trim() {
int len = value.length;
valueはchar型の配列です。lengthは長さを返します。
もし、value = nullの時、value.lengthはNullPointerExceptionを投げます。
Javaでは配列が「null」か「長さ0」かで意味が異なります。(引用: nullか長さ0の配列か)
長さ0ならNullPointerExceptionは投げないはずです。
結論
parseDoubleの内部でString型のフィールドに対してlengthを取っているため、その時に
NullPointerExceptionをthrowする。そのため、throwが2つあります、というわけでした。
0 件のコメント:
コメントを投稿