Android Studio最速入門~効率的にコーディングするための使い方

第41回コードフォーマット

はじめに

たいていのIDEが備えているソースコードの整形機能―――コードフォーマットについて解説します。Android Studioができるコードフォーマットは次の3種類です。

インポートの最適化
インポート文の最適化を行います。Eclipseの「ソース → インポートの編成」に相当します。
コードフォーマット
指定されたルールに基づいてソースコードを整形します。Eclipseの「ソース → フォーマット / 要素のフォーマット」に相当します。
アレンジメント
指定されたルールに基づいて、ソースコード内の要素を並び替えます。Eclipseの「ソース → メンバーのソート」に相当します。

できることはEclipseとさほど変わりありません。Eclipseとの機能的な大きな違いは ファイルの保存のタイミングで自動でフォーマットできないこと です。

コードフォーマットの基本

Android Studioのコードフォーマットのルール(コードスタイル)「Preferences / Code Style」で設定します。この設定は「Project Settings」に属するので、プロジェクトごとに変更することができます。

図1 ⁠Preferences / Code Style」設定画面
図1 「Preferences / Code Style」設定画面

インスペクションと同じようにコードスタイルも「Scheme」として複数の設定を持つことができます。ただし、追加したコードスタイルの内容そのものはIDEの設定として保存されます。デフォルトの状態では「Project」「Default」の2つのSchemeが登録されています。キーバインド(Keymap)やカラー設定(Color & Fonts)ではデフォルトの設定を変更することはできませんが、コードスタイルはデフォルトの値を変更することができます。

もうすこし内情について説明します。コードスタイルの設定はProject Structureに属しているにもかかわらず<AS_HOME>/config/codestylesに保存されます。つまり、いくつもScheme(コードスタイル)を設定してもそれはIDE固有の設定として記録されます。個人で利用する分には問題ないのですが、複数人でプロジェクトを共有する場合、自分以外の人に自分が設定したコードスタイルを渡すことができません。

そこで登場するのがデフォルトで登録済みの「Project」コードスタイルです。このコードスタイルのみ、設定情報が<PROJECT_HOME>\.idea\codeStyleSettings.xmlに保存されます。このファイルをバージョン管理システムに登録して共有することでコードスタイルも共有されます(この話は第35回につながります⁠⁠。

「Project」コードスタイルのみ共有されるのであれば、それ以外のスタイルは何のためにあるのか?という疑問については「Preferences / Code Style」設定画面の「Manged...」ボタンから知ることができます。

この「Code Style Schemes」ダイアログの「Copy to Project」ボタンを押すと、選択中のコードスタイルの内容が「Project」コードスタイルにコピーされます。どうやら、常に「Project」コードスタイルを使うようにし、その内容をプロジェクト毎に変更していくという共有方法をとります。

「Preferences / Code Style」の詳しい設定については次回で紹介する予定です。

インポートの最適化

無駄なインポート文を削除したり、指定されたルールに従ってインポート文を最適化する機能ですが、コーディング時に適時行う方法と、明示的に"Optimize Imports..."コマンドを実行して行う方法の2種類あります。

まずはインポート最適化に関するルール設定について説明します。設定箇所は「Preferences / Code Style / Java」「imports」タブです。

図2 ⁠Preferences / Code Style / Java」設定画面の「imports」タブ
図2 「Preferences / Code Style / Java」設定画面の「imports」タブ

設定できる箇所はそれほど多くは無いのですが、英語表記ということもあって少々わかりづらいです。またIntelliJ由来のため無意味な設定項目もあります(⁠⁠JSP imports layout」がそう⁠⁠。

General
インポート最適化の全般的な設定です。
  • Use single class import:ONにするとアスタリスク*を使わず、クラスひとつずつ インポート文を記述します。
  • Use fully qualified class names:ONにするとインポート文を使わず、常にクラスの完全修飾名を展開します。正直、なんのためにあるオプションなのかわかりません。
  • Insert imports for inner classes:ONにすると内部クラスに対してもインポート文を展開します。これをONにすると、一見してそのクラスが内部クラスなのか通常のクラスなのか見分けが付かなくなるので、筆者はこれをONにするのは好みません。
  • Use fully qualified class names in javadoc:ONにすると、Javadoc中のクラスを完全修飾名で記述します。Javadoc中でしか参照しないクラスのために インポート文を追加するのが許せない人はONにしましょう。筆者は、そのあたりはおおらかなのでOFFにしています。
  • Class count to use import with '*':インポート文でアスタリスクを使うまでの閾値を指定します。最初に紹介した「Use single class import」をONにしていても 同じパッケージのクラス を、ここで指定した値以上インポートするとアスタリスクに展開します。
  • Names count to use static import with '*':上の項目のスタティックインポート版です。ここで指定した値以上のメンバやメソッドをスタティックインポートするとアスタリスクに展開します。
JSP imports layout
JSP(JavaServer Pages)でのインポート文の設定です。そもそもAndroid StudioはJSPの編集をサポートしていないので、この項目自体が無意味です。元になったIntelliJ IDEAのUltimate EditionがJSPをサポートしているので、その名残です。
Package to Use Import with '*'
「General」にある「Use single class import」「Class/Names count to use~」に関わりなく、常にアスタリスク指定でインポートしたいパッケージを指定します(スタティックインポートも扱えます⁠⁠。
Import Layout
インポート文の並び順を指定します。パッケージ別に指定できたり、空行の挿入箇所を指示できたりと、見かけによらず高機能です。もちろんスタティックインポートも対象です。

どのような設定が望ましいかは、個人の嗜好であったりプロジェクトのルールに依ります。たとえば、筆者の場合はこうです。

  • インポートにアスタリスクを使うのは好きでは無い
    • 「Use single class import」をON
    • 「Class count to use import with '*'」99999 を指定(いかなる場合もアスタリスク展開させない)
  • 反対にスタティックインポートにアスタリスクを使うのを好む
    • 「Names count to use static import with '*'」3 を指定(3つ以上、同じクラスのメンバをスタティックインポートしたらアスタリスク展開する)

JUnit4やhamcrestの場合は常にアスタリスク展開したかったので、それらを「Package to Use Import with '*'」に指定していましたが、Android StudioはJUnit3ベースなので、今のところ使い道がありません。

コーディング時に適時インポートの最適化を行う

「Preferences / Code Style / Java / Imports」の設定はあくまでインポート文のスタイル指定です。既存のファイルを編集する時は別として、新規にファイルを作成する場合、インポート文はコーディングしながら自動展開していくのが普通だと思います。なんとなくエディタの話に戻りますが、コーディング中に適時インポートの最適化を行うかどうかの設定が いくつか あります。

その代表格が「Preferences / Editor / Auto Import」です。

図3 その代表格が「Preferences / Editor / Auto Import」設定画面
図3 その代表格が「Preferences / Editor / Auto Import」設定画面
Insert import on paste
コード片をペーストした際にインポートが必要だった場合の振る舞いを指定します。
  • All:必要なインポート文を自動的に追加します。
  • Ask:必要なインポート文を確認するダイアログを表示し、インポートするかどうかを問い合わせます(筆者はこの設定を好んでます⁠⁠。
  • None:インポート文が必要だとしても何もしません。
Show import popup
インポートする候補をポップアップ表示します。通常ONにします(これをOFFにする理由を知りたいくらいです⁠⁠。遙かかなた昔は意味のあったオプションなのですが、IntelliJ IDEA13をベースにしているAndroid Studioのコード補完機能はより高度になっているので、このオプションがONであろうとOFFであろうと、インポートするパッケージの候補が表示されます。
Optimize imports on the fly
コーディングしながらリアルタイムにインポートの最適化を行います。最適化の精度はそれほど高くありません。コードスタイル設定で「Use single class import」を有効にしていても、すでにimport java.util.*;などの記述があれば、それを優先します。
基本的にONにすることをオススメします。ただし、チーム開発で他人が作ったコードを編集する時など涙をのんでOFFにする場合もあります。時と場合によっては「インポートの最適化」は寝た子を起こすな的な意味で余計なお世話になるからです。
また不要なインポート文を除去する場合は、これの他にインスペクションの「Imports / Unused import(editor light)」を有効にする必要があります。まわりくどいですね。
Add unambiguous imports on the fly
MapArrayListなどインポートするパッケージが一意な場合、利用者に問い合わせなく勝手にインポートを追加するかどうかを指定します。通常のコード補完でも似たような振る舞いをしているので、ONにしておいて邪魔になることはないでしょう。
Exclude from Inport and Completion
インポートやコード補完の候補から除外するパッケージを指定します。ここで設定しなくてもコード補完の候補リストから除外パッケージを指定できます。むしろ、そのほうが便利です。
図4 コード補完時に自動インポートの除外パッケージを指定する
図4 コード補完時に自動インポートの除外パッケージを指定する
どちらかというと間違えて除外設定してしまったパッケージ指定を削除するために用いるのが主な使い道になるでしょう。

コーディングしながら半自動的にインポート文を展開していく書き心地はIDEによって微妙に異なるので、Eclipseからの移行組は特に違和感を感じる部分ではないでしょうか。

コーディング中のインポートに関わる設定は、このほかにインスペクションとインテンションにもあります。まずはインスペクションですが「Imports」カテゴリにいくつか設定があります。

'*' import
パッケージ全体のインポート(アスタリスク指定のインポート文)を警告します。ここをONにすると「Preferences / Code Style」「imports」設定に関わりなく警告してきます。
Import from same package
自身が属するパッケージをインポートしている場合に警告します。多くの読者は、そんなマヌケな事はしないと思いますが、時折このようなコードを見て世界の広さを感じることがあります。
'java.lang' import
java.langパッケージをインポートしている場合に警告します。
Redundant import
重複したインポート文があれば警告します。
Single class import
クラス指定のインポートをしている場合に警告します。\* import」の真逆です。こちらも「Preferences / Code Style」「imports」設定に関わりなく警告してきます。
Static import
スタティックインポートを使っていると警告してきます。Optionsに「staticインポートを許可するクラス(Statically importable Classes⁠⁠」を指定することができます。また「テストコードでのみ許可する(Ignore in test code⁠⁠」などユニークなオプションがあります。
図5 ⁠Static import」の設定項目
図5 「Static import」の設定項目
Unused import
使っていないパッケージのインポート文があれば警告します。次の「Unused inport(editor light)」とやることは同じですが、こちらは第40回で紹介した"Inspect Code..."用です。
Unused inport(editor light)
使っていないパッケージのインポート文があれば警告します。⁠Preferences / Editor / Auto Imports」「Optimize imports on the fly」と組み合わせると、不要なインポート文を即座に削除します。
常にインポート文が最適化してあるのは気持ちの良い事なのですが、あまりにも即時過ぎると、ちょっとコードを弄っただけでインポート文を削除するので、それが思考の妨げになる時があります。インポート文の最適化もやり過ぎ注意ですね。

続いてインテンション(⁠⁠Preferences / Intentions⁠⁠)です。カテゴリは「Declaration」「Imports」の2ヵ所です。インテンションはお節介機能なので、どれを有効にしておくかは利用者の好みです。

Declaration / Replace Implements with Static Import
implementsextendsに指定しているインターフェイスやクラスの利用箇所をスタティックインポートに置き換えます。
Declaration / Replace On Demand Import with Single Class Imports
パッケージインポート(アスタリスク指定)をシングルクラスのインポートに置き換えます。
Declaration / Replace Qualified Name with Import
完全修飾で指定しているクラスやインターフェイスをインポート文に置き換えます。
Imports / Add On Demand Static Import
スタティックインポートに変換可能ならばスタティックインポートに置き換えます。
Imports / Add Single-Member Static Import
スタティックインポートをアスタリスク指定ではなくシングルメンバで記述します。
Imports / Expand Static Import
スタティックインポートをやめて元に戻します。これをONにする用途はそう無いでしょう。

これらの設定を行った上で、普通にコーディングしていれば普通にインポートの最適化が行われていくと思います。Eclipse移行組の方は、Eclipseとの書き味の違いを上記の設定と慣れでカバーしましょう(とはいえ大半は慣れるしか無いのですけど……⁠⁠。

コマンドを実行してインポートの最適化を行う

メニューバーの「Code → Optimize Imports...」からインポートの最適化を行う方法です。

こちらのコマンドによる方法だと、よりコードスタイルに準じたインポートの最適化が行われます。先ほどの「on the fly」モードではできなかったインポートスタイルの統一(アスタリスク指定、またはシングルクラス指定)も行います。

コマンドを実行すると図6のようなダイアログが表示されます。

図6 ⁠Optimize Imports」ダイアログ
図6 「Optimize Imports」ダイアログ

ダイアログには「インポートの最適化」を行う対象を選ぶ部分がありますが、その表示はコマンド("Optimzie Imports...")を実行した場所によって若干内容が変わります。

見ての通り指定したディレクトリ配下に対して「インポートの最適化」を施すことができるので「Projectツールウィンドウ」あたりから実行するのが適切だと思います(ちょうど「Projectツールウィンドウ」のコンテキストメニューにも「Optimize Imports...」があります⁠⁠。

Eclipseの「インポートの編成」の場合、インポートが不完全なコードもインポート文を補完してあるべき姿に最適化していきますが、Android Studioではインポートしていないパッケージの補完は行いません。あくまで今のソースコードに記述しているインポート文だけが最適化の対象となります。

インポートしていないパッケージが存在する状態は「単なるコーディングエラーなのでコーディング中に解決せよ」というスタンスなんでしょうか。ただ、そのような状態でコーディングを進める事はほとんどないため、筆者はこの振る舞いに不満を持ったことがありません(むしろ、今回の比較を行って違いに気づいたくらいです⁠⁠。Eclipse移行組で、Eclipseのこの特性を利用したコーディングに慣れていたりすると、この振る舞いの違いはストレスの元になりそうです。

コードフォーマット

今回のド本命です。コードスタイルの設定は「Preferences / Code Style」で言語ごとに細かく指定することができます。

それぞれの設定項目の詳細については次回まとめて紹介します。今回はコードフォーマットの使い方と予備知識を中心に説明します。

コードフォーマットはメニューバーの「Code → Reformat Code...」から実行します。コマンドを実行すると先ほど紹介した「インポートの最適化」と似たようなダイアログが表示されます。

図7 ⁠Reformat Code」ダイアログ
図7 「Reformat Code」ダイアログ

こちらもインポートの最適化同様、コマンドを実行した場所によってダイアログの内容が若干変わります。使い道としては「Projectツールウィンドウ」のコンテキストメニューから実行する事のほうが多いのでは?と思います。

インポートの最適化と違う点は、エディタ上で範囲選択してからコマンド("Reformat Code...")を実行すると、その選択範囲のみをコードフォーマットの対象とすることができます(ダイアログの「Selected Text」が選択できるようになります。Eclipseの「ソース → 要素のフォーマット」と同等です⁠⁠。

「Reformat Code」ダイアログ下側のチェックボックスを見てもわかるとおり、このコマンドから「インポートの最適化(Optimize imports⁠⁠」と「アレンジメント(Rearrange entries⁠⁠」も一度に実行することができます。また「Only VCS changed text」をONにすると、バージョン管理下で変更を行ったファイルのみを処理の対象とすることができます……のハズですが、実際に試すと変更してないファイルも処理されました(バグでしょうか?0.4.4で確認しました⁠⁠。

インポートの最適化の「Optimize Imports」ダイアログにもあった「Do not show this dialog in the future」ですが、これをONにすると、以降 "Optimize Impors..."や"Reformat Code..."コマンドを実行しても、事前にダイアログが出なくなります。これを元に戻したい場合は、図8のように「Preferences / Editor」の2つの項目をONにします。

図8 ⁠Preferences / Editor」設定画面
図8 「Preferences / Editor」設定画面

この場所が非常にわかりづらいため、間違ってダイアログを非表示にして元に戻せなくて困っている人も多いと思います。

最近のAndroid Studioでは、Eclipseのようにコードフォーマットして欲しくない範囲をコメントで指定できるようになりました。たとえばリスト1のように@formatter:off@formatter:onで囲んだ範囲はコードフォーマットの対象にはなりません。

リスト1 "@formatter:off ~ on"でコードフォーマットの対象から外す
// @formatter:off
TextView textView = (TextView)findViewById(R.id.textView);
textView.setText(getIntent().
                 getStringExtra("inputText"));
// @formatter:on

この機能を使うには「Preferences / Code Style / General」「Enable formatter markers in comments」をONにしておく必要があります。また、この設定画面でコードフォーマット抑止用のコメントキーワードを変更することができます。ただ、デフォルト値がEclipseのそれと同じなのでわざわざ変更する必要もないと思います。

図9 ⁠Preferences / Code Style / General」設定画面
図9 「Preferences / Code Style / General」設定画面

コード生成に関連するコードスタイルの設定

コードフォーマットのスタイル設定を行う「Preferences / Code Style / Java」ですが、その中の「Code Generation」タブは"Reformat Code..."で適用するスタイルの設定ではなく、"Generate..."などで生成するコードのスタイルを設定します。

ついでなので仕方ないのでしょうがコードスタイルの設定には「Code Generation」のように、直接関係ない設定が紛れ込んでいる場合があります。

Naming
インスタンス変数(Field⁠⁠、クラス変数(Static Field⁠⁠、引数(Parameter⁠⁠、ローカル変数(Local variable)それぞれの接頭子(Name prefix)と接尾子(Name suffix)を定義します。採用しているコーディングルールや好みにもよると思いますが、筆者はここを設定した事はありません。
仮に図12のような古典的なルールを定義したとしましょう(ローカル変数の接頭子にアンダースコア_を付けます⁠⁠。
図12 ローカル変数の接頭子を指定する
図12 ローカル変数の接頭子を指定する
一応というか当然それなりの影響力がありまして、コード補完の候補もここで定義した内容に従うようになります。
図13 ローカル変数名のコード補完の候補に接頭子が付くようになる
図13 ローカル変数名のコード補完の候補に接頭子が付くようになる
なお「Prefer longer names」をONにするとコード補完に出てくる候補は文字数の長い順になります。OFFの場合は、文字数の短い順になります。これは接頭子、接尾子とは関係なく機能するオプションです。
図14 ⁠Prefer longer names」のON/OFFによる補完候補の違い
図14 「Prefer longer names」のON/OFFによる補完候補の違い
こんなどーでもいいことまで設定できるところを見るにつけ、すごいなぁという思いとやり過ぎだろうというあきれた思いが交差します(こうゆう拘りが良い方向にはたらく事がよくあるので侮れません⁠⁠。
Final Modifier
自動生成したコードのローカル変数(local variable)や引数(parameter)にFinal修飾子をつけるかどうかを指定します。
  • Make generated local variables final:ローカル変数にfinalをつける
  • Make generated parameters final:引数にfinalをつける
finalを付けたい気持ちはわかるのですが、そこまで徹底できないので筆者はこの設定を両方ともOFFにしています。
Comment Code
"Comment with Line Comment"や"Comment with Block Comment"でコメントアウトするときに、その行の最初(1桁目)にコメント宣言///* ~ */を記述するかどうかを指定します。
  • Line comment at first column:行コメントを行の先頭から始める
  • Block comment at fist column:ブロックコメントを行の先頭から始める
これがOFFだと文字が始まる直前にコメントが挿入されます。ブロックコメントだとON/OFFの違いがわかりづらいです。個人的には、2つともONにしておくのが好みです。
図15 ⁠Comment Code」の設定が両方とのONの場合(クリックすると動きがわかります)
「⁠Comment Code」の設定が両方とのONの場合` &title=`図15 ⁠Comment Code」の設定が両方とのONの場合` &width=`391` />
図16 ⁠Comment Code」の設定が両方とのOFFの場合(クリックすると動きがわかります)
「⁠Comment Code」の設定が両方とのOFFの場合` &title=`図16 ⁠Comment Code」の設定が両方とのOFFの場合` &width=`400` />
Override Method Signature
自動生成したオーバライドメソッド(インターフェイスの実装メソッド含む)のシグネチャに関する設定です。
  • Insert @Override annotation@Overrideアノテーションを付けるかどうかを指定します。イマドキのJava開発なら迷わずONにしましょう。
  • Repeat synchronized modifiersynchronized宣言を付けるかどうかを指定します。そもそもメソッド宣言にsynchronizedが付いているコードを見かける方が稀です。ほとんど出番がないと思いますが、とりあえずONにしています。
Order of Members
「インテンションやリファクタリングによってメソッドやフィールドを自動生成した場合に、どこに生成するかを指定します」とヘルプには記述してありましたが、実際そうなのか結構アテになりません。次の節で説明する「アレンジメント」とも連動していないので、今となっては死んでる設定項目だと思って無視していよいでしょう。筆者も、この設定を気にしたことがありません。

アレンジメント

Eclipseの「設定 → 外観 → メンバー・ソート順序」に相当します(ダジャレではありません⁠⁠。実行はメニューバーの「Code → Rearrange Code」で行います。前述した"Optimize Imports..."や"Reformat Code..."と異なりコマンド名の末尾に "..." が付かないため、コマンド指定後即座に実行されます(実行前にダイアログとか出てきません⁠⁠。

それと律儀にアレンジメントだけ行います(コードフォーマットは実施しない⁠⁠。そのため、このコマンド単独で利用するより"Reformat Code..."のオプションとして指定する用途のほうが多いのでは?と思います。⁠だったら、はじめから"Reformat Code..."にまとめておけば……」と言いたくなりますが、この機能の生い立ちに起因するためか、こんなコマンド体系になっています。

生い立ちといっても大げさなものではありません。元々この機能、IntelliJのプラグインとして提供されていたのですが、その人気と完成度の高さからIntelliJ本体に取り込まれました(筆者の記憶が正しければ、IDEA12からです⁠⁠。プラグインとしての歴史はそこそこ長いですが、IntelliJ/Android Studioの機能としては若いです。そうもあってか、たまにエラーを吐きます。

アレンジメントの設定

「Preferences / Code Style / Java」「Arrangement」にあります。"Reformat Code..."で「Rearrenge entries」を有効にすればコードフォーマット時にも適用されるので、設定項目がここにあってもそんなにおかしくは無いです。

元がJetBrains製ではないプラグインという背景もあってか、設定画面のユーザインターフェイスはかなり独特です。

図19 ⁠Preferences / Code Style / Java」設定画面の「Arrangement」タブ
図19 「Preferences / Code Style / Java」設定画面の「Arrangement」タブ

Andorid Studio 0.4.4でみるとUIが微妙にわかりづらくなっていますが、上半分の(1)~(3)の設定が「Grouping rules(グルーピングのルール⁠⁠」で、下半分が「Matching rules(組合せのルール⁠⁠」になります。

「Grouping rules」は関係のあるメソッドをグループ化するためのルールを指定します。丸数字の1~3が優先度で、その隣のチェックボックスがそのルールを適用するかどうかのスイッチになっています。優先度は右上の「≫」で隠れている上下アイコンで変更することができます。

Keep getters and setters together
同じプロパティに対するgettersetterをまとめるかどうかを指定ます。
Keep overridden methods together
オーバライド(または実装)したメソッドの並び順を指定します。
  • keep order:親クラス(またはインターフェイス)の定義順に並び替える
  • order by name:アルファベット順に並び替える
Keep dependent method together
依存関係のあるメソッドの並び順を指定します。⁠依存関係のあるメソッド」とはリスト2のようなメソッド群を指します。
  • depth-first order:深さ優先で並び替えします。
  • breadth-first order:幅優先で並び替えします。先ほど例示したリストが幅優先の例です。
リスト2 依存関係のあるメソッド群の例
void aaa() {
  bbb();
  ccc();
}
void bbb() { AAA(); }
void AAA() {}
void ccc() {}

「Matching rules」はメンバやメソッドの並び順を指定します。こちらも右上端の「≫」アイコンでルールの優先度を変更したり、ルールそのものを追加したり削除することができます。見かけによらず設定できるルールは多彩です。むしろこのルールが提供されるようになったため「Code Generation」「Order of Members」が無用の長物になっています。

図20 ⁠Matching rules」のルール設定の例(クリックすると動きがわかります)
「⁠Matching rules」のルール設定の例` &title=`図20 ⁠Matching rules」のルール設定の例` &width=`400` />

筆者は、ここまでコードの並び順に執着がないため "Rearrenge Code"自体をめったに使ったことがありません。この記事の執筆のためいろいろ調べましたが、こんなに"Rearrenge Code"を使ったのは今回がはじめてと言っても過言では無いです。

まとめ

Android Studioのソースコード整形機能についてできること(インポートの最適化、コードフォーマット、アレンジメント)とその使い方を中心に紹介しました。

次回は、整形機能のうちでもコードフォーマットに注目して、そこで設定できるフォーマットのルールを紹介します。

おすすめ記事

記事・ニュース一覧