発火後忘失

FIRE AND FORGET

Eclipse4.5でimportの編成を行うと並び順が変わる

参考リンク

元ネタはこちら:

関連するバグレポートは、(上記回答にも書きましたが)こちら:

今回使用したソースはこちら(Mainクラスでimportソート順が見られます):

事象

Eclipse(4.4/4.5とも)のimportの並び順は Organize Imports で設定できるのですが、デフォルトでは以下のようになっています。

f:id:yukihaned:20151220164039p:plain

この設定のまま 4.5 で Source > Organize Imports (Ctrl+Shift+O; 日本語ではimportの編成、でしょうか)を行うと次のような並び順になります。

import java.net.HttpURLConnection;
import java.util.ArrayList;

import javax.swing.JFrame;

import org.w3c.dom.DOMException;

import com.ClassCom;

import a.ClassA;
import javaj.ClassJavaj;
import jp.mycompany.myproject.ClassJp;

日本語で説明するとこんな感じでしょうか。

  • 設定で順序が明示されているものはその順に並ぶ。
  • 設定で順序が明示されていないものは、明示されたパッケージの後ろに、アルファベット順で並ぶ。

次に 4.4 の場合です。

import java.net.HttpURLConnection;
import java.util.ArrayList;

import javaj.ClassJavaj;

import javax.swing.JFrame;

import jp.mycompany.myproject.ClassJp;

import org.w3c.dom.DOMException;

import a.ClassA;

import com.ClassCom;

こうして比較して見てみると、随分違いますね。
前述bug reportには "best match" という用語が何度か登場していて、特定のアルゴリズムを指す名称のような雰囲気があるのですが、具体的にどういうアルゴリズムなのかは検索しても分かりませんでした。
そこで実際に試してみたところ、並び替えた結果は次のようになっているようでした。

  • 設定で順序が明示されているものはその順に並ぶ。
  • 設定で順序が明示されていないものは、アルファベット順に並べたとき、直後にくる明示されたものの設定に従う。

今回の場合ですと、それぞれ、 javajjavaxjporgacom の設定に従っているわけですね。

対策

日本で使っていてこの問題に遭遇する頻度は jp パッケージが最も高いと思うのでこれを例に挙げると、 Java > Code Style > Organize Imports の設定で、 javaxorg の間に jp を追加しておけば、4.4の並び順が4.5でも再現できることになります。

アドバンス

そもそもEclipseのデフォルト設定がなぜこの順になっているかを考えると、

  • 標準的なパッケージほど先頭に置く
  • (逆に言うと)自作パッケージは最下部

という想定なのだと思われます。
ここで自作パッケージは com (とか org )しか考慮されていないのが非アメリカ人にとって問題だったのでしょう。
日本人としては、Organize Importsの設定で、最下部に jp が入っていれば問題が起きにくかったと言えます。

4.5の挙動はその意味では妥当だと思います。が、以前のコードに変更が入るとなると、すんなりとは受け入れられない場面もあることは容易に想像できますね…