2017年1月13日金曜日

【TAネタ】parseDoubleメソッドにはthrowが1つしかないのに、APIには2つあるのはなんで?

きっかけ

プログラミングが得意ではなかった1年生が4年後にTAをやるなんて思いもしなかった...(遠い目)

僕はTAでレポートの仮採点をしています。その時の質問をネタにしました。

parseDoubleメソッドにはthrowが1つしかないのに、APIには2つあるのはなんで?

JavaにはparseDoubleというメソッドがあります。このメソッドは、変換可能であればString型の文字列をDobule型の数値に変換することができます。

さて、APIを見てみるとこんなことが書いてあります。





Throws:
NullPointerException - if the string is null
NumberFormatException - if the string does not contain a parsable double.

どこが問題かと言うと、parseDoubleは最初に、

public static double parseDouble(String s)
                          throws NumberFormatException

と書いているのです。


NumberFormatExceptionはthrowで明示されているのに、NullPointerExceptionはどこでthrowされているのでしょう?

これを調べるにはJDKの実装を見てみるのが早いと思いました。
openJDKのDoubleを読んでみると、537行目にparseDoubleがあります。

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つあります、というわけでした。

2017年1月12日木曜日

texstudioの設定が変更されていた件

きっかけ

ちょっと前にMacをEl Capitanにアプデしました。
あんまりTeXも使う機会はなかったのですが、修論も近いので久しぶりに動かしてみることになりました。

ところが、動かない!

なんで??
そういえば何か重大な変更があったような...というのを思い出した次第です。

なんで動かないの?

僕は普段、TeXstudioを利用しています。優れものです。
ところが、コンパイルを押すとcommond not foundが返ってくるのです。
TeXstudioの環境設定を見ると、/usr/local/texbin/の中のコマンドを指しているようです。

ところが、El CapitanからRootlessのため、/Library/以下にtexコマンドが移ったようです。(引用: TeX界の El Capitan 迎撃戦記)

というわけで

簡単です。/Library/以下からtexコマンドを見つければ良い。
僕の場合、/Library/TeX/Distributions/Programs/texbin/にありました。
設定を書き換えて、終了です。
おつかれさまでした。