Javaのリファクタリングとソースアクション
Visual Studio Codeは、ソースコードのリファクタリングや、コーディング中にコードを生成したり問題を修正したりするソースアクションなど、多くのオプションを提供しています。これらの機能にアクセスするには、電球 💡が表示されたときにクリックするか、エディタービューを右クリックしてソースアクション...を選択します。
サポートされているコードアクションのリスト
- リファクタリング
- 変数に代入
- 匿名クラスをネストされたクラスに変換
- 匿名クラス作成に変換
- 拡張forループに変換
- ラムダ式に変換
- 静的インポートに変換
- リファクタリングを抽出
- インラインリファクタリング
- ブール値を反転
- 移動
- 名前の変更
- 型変更
- ソースアクション
- その他のサポートされているコードアクション
リファクタリング
Javaプログラムのリファクタリングの目的は、プログラムの動作に影響を与えることなく、システム全体でコード変更を行うことです。VS CodeのJava言語サポートは、多くのアクセスしやすいリファクタリングオプションを提供します。
リファクタリングの呼び出し
リファクタリングコマンドはエディターのコンテキストメニューから利用できます。リファクタリングしたい要素を選択し、右クリックしてコンテキストメニューを開き、リファクタリング...を選択します。

すると、利用可能なリファクタリングオプションがすべて表示されます。
変数に代入
式をローカル変数またはフィールドに代入します。
例
以前
Arrays.asList("apple", "lemon", "banana");
以後
List<String> fruits = Arrays.asList("apple", "lemon", "banana");
また、コンストラクター内の未使用のパラメーターを新しいフィールドに代入するためにも使用できます。
匿名クラスをネストされたクラスに変換
匿名内部クラスをメンバークラスに変換します。
例
匿名クラスInterface(){...}をクラスClazzのメンバーに変換しましょう。
以前
public class Clazz {
public Interface method() {
final boolean isValid = true;
return new Interface() {
public boolean isValid() {
return isValid;
}
};
}
}
以後
public class Clazz {
private final class MyInterface extends Interface {
private final boolean isValid;
private MyInterface(boolean isValid) {
this.isValid = isValid;
}
public boolean isValid() {
return isValid;
}
}
public Interface method() {
final boolean isValid = true;
return new MyInterface(isValid);
}
}
匿名クラス作成に変換
ラムダ式を匿名クラス作成に変換します。
例
変数runnableにはラムダ式が代入されています。これを匿名クラス作成に変換しましょう。
以前
public void method() {
Runnable runnable = () -> {
// do something
};
}
以後
public void method() {
Runnable runnable = new Runnable() {
@Override
public void run() {
// do something
}
};
}
参照: ラムダ式に変換
拡張forループに変換
単純なforループをfor-eachスタイルに変換します。
例
以前
public void order(String[] books) {
for (int i = 0; i < books.length; i++) {
// do something
}
}
以後
public void order(String[] books) {
for (String book : books) {
// do something
}
}
ラムダ式に変換
匿名クラス作成をラムダ式に変換します。
例
匿名クラスRunnable(){...}をラムダ式に変換しましょう。
以前
public void method() {
Runnable runnable = new Runnable(){
@Override
public void run() {
// do something
}
};
}
以後
public void method() {
Runnable runnable = () -> {
// do something
};
}
参照: 匿名クラス作成に変換
静的インポートに変換
フィールドまたはメソッドを静的インポートに変換します。
例
Assert.assertEquals()の呼び出しを静的インポートに変換しましょう。
以前
import org.junit.Assert;
...
public void test() {
Assert.assertEquals(expected, actual);
}
以後
import static org.junit.Assert.assertEquals;
...
public void test() {
assertEquals(expected, actual);
}
定数に抽出
選択された式から静的最終フィールドを作成し、フィールド参照を置き換え、同じ式が出現する他の場所を書き換えます。
例
πの値:3.14を定数に抽出しよう。
以前
public double getArea(double r) {
return 3.14 * r * r;
}
以後
private static final double PI = 3.14;
public double getArea(double r) {
return PI * r * r;
}
参照: 定数をインライン化
フィールドに抽出
新しいフィールドを宣言し、選択された式で初期化します。元の式はフィールドの使用に置き換えられます。
例
変数areaをクラスSquareのフィールドに抽出しましょう。
以前
class Square {
public void calculateArea() {
int height = 1;
int width = 2;
int area = height * width;
}
}
以後
class Square {
private int area;
public void calculateArea() {
int height = 1;
int width = 2;
area = height * width;
}
}
変数宣言を選択すると、その変数をフィールドに変換します。
メソッドに抽出
現在選択されているステートメントまたは式を含む新しいメソッドを作成し、選択を新しいメソッドへの参照に置き換えます。この機能は、長くて乱雑な、または過度に複雑なメソッドを整理するのに役立ちます。
例
式height * widthを新しいメソッドに抽出しよう。
以前
public void method() {
int height = 1;
int width = 2;
int area = height * width;
}
以後
public void method() {
int height = 1;
int width = 2;
int area = getArea(height, width);
}
private int getArea(int height, int width) {
return height * width;
}
参照: メソッドをインライン化
ローカル変数に抽出
現在選択されている式に割り当てられた新しい変数を作成し、選択を新しい変数への参照に置き換えます。
例
式platform.equalsIgnoreCase("MAC")を新しい変数に抽出しよう。
以前
public void method() {
if (platform.equalsIgnoreCase("MAC")) {
// do something
}
}
以後
public void method() {
boolean isMac = platform.equalsIgnoreCase("MAC");
if (isMac) {
// do something
}
}
抽出後、同じトランザクションで名前変更も実行できます。
参照: ローカル変数をインライン化
定数をインライン化
定数参照をその定義値で置き換えます。
例
定数PIをその定義値3.14に置き換えましょう。
以前
private static final double PI = 3.14;
public double getArea(double r) {
return PI * r * r;
}
以後
private static final double PI = 3.14;
public double getArea(double r) {
return 3.14 * r * r;
}
参照: 定数に抽出
ローカル変数をインライン化
冗長な変数の使用をその初期化子で置き換えます。
例
変数isMacを直接ブール式に置き換えましょう。
以前
public void method() {
boolean isMac = platform.equalsIgnoreCase("MAC");
if (isMac) {
// do something
}
}
以後
public void method() {
if (platform.equalsIgnoreCase("MAC")) {
// do something
}
}
参照: ローカル変数に抽出
メソッドをインライン化
メソッドへの呼び出しをメソッドの本体で置き換えます。
例
メソッドgetArea(int height, int width)を直接式height * widthに置き換えましょう。
以前
public void method() {
int height = 1;
int width = 2;
int area = getArea(height, width);
}
private int getArea(int height, int width) {
return height * width;
}
以後
public void method() {
int height = 1;
int width = 2;
int area = height * width;
}
参照: メソッドに抽出
条件を反転
条件内のブール式を反転します。
例
if文内のブール式を反転させましょう。
以前
public void method(int value) {
if (value > 5 && value < 15) {
// do something
}
}
以後
public void method(int value) {
if (value <= 5 || value >= 15) {
// do something
}
}
ローカル変数を反転
ローカルのブール変数を反転します。
例
変数validを反転させましょう。
以前
public void method(int value) {
boolean valid = value > 5 && value < 15;
}
以後
public void method(int value) {
boolean notValid = value <= 5 || value >= 15;
}
移動
選択した要素を移動し、すべての要素への参照を修正します(他のファイルでも)。利用可能なアクションは次のとおりです。
- クラスを別のパッケージに移動
- 静的またはインスタンスメソッドを別のクラスに移動
- 内部クラスを新しいファイルに移動
例
静的メソッドprint()をクラスOfficeからクラスPrinterに移動させましょう。
以前
public class Office {
public static void main(String[] args) {
print();
}
public static void print() {
System.out.println("This is printer");
}
static class Printer { }
}
以後
public class Office {
public static void main(String[] args) {
Printer.print();
}
static class Printer {
public static void print() {
System.out.println("This is printer");
}
}
}
静的メソッドが自身のクラスよりも他のクラスで多く使用されている場合、その静的メソッドでリファクタリングを移動します。
クラスを別のパッケージに移動します。現在、ファイルエクスプローラーからの移動リファクタリングはサポートされていません。
内部クラスを新しいファイルに移動します。
名前の変更
デフォルトのショートカット: F2
選択した要素の名前を変更し、すべての要素への参照を修正します(他のファイルでも)。
例
クラスFooをBarに名前変更しましょう。
以前
public class Foo {
// ...
}
public void myMethod() {
Foo myClass = new Foo();
}
以後
public class Bar {
// ...
}
public void myMethod() {
Bar myClass = new Bar();
}
名前変更リファクタリングを呼び出すショートカットはF2です。エディターで識別子に対してショートカットを呼び出すと、エディター内に小さなボックスが表示され、そこで識別子の名前を変更できます。Enterを押すと、その識別子へのすべての参照も変更されます。
ファイルエクスプローラーからのフォルダーやファイルの名前変更リファクタリングもサポートされています。変更を要求した後、影響を受けるファイルのプレビューが提供され、それらの変更をどのように適用するかを決定できます。

解決された型をvar型に変更
varを使用してローカル変数を宣言します。
例
以前
String s = "";
以後
var s = "";
参照: var型を解決された型に変更
var型を解決された型に変更
解決された型を使用してローカル変数を宣言します。
例
以前
var s = "";
以後
String s = "";
参照: 解決された型をvar型に変更
ソースアクション
ソースアクションは、共通のコード構造や繰り返し要素を生成するために使用できます。その中には、コーディング中にコードの問題を即座に修正するのに役立つクイックフィックスもあります。
コンストラクターを生成
クラスのコンストラクターを追加します。
デリゲートメソッドを生成
デリゲートメソッドを生成
メソッドをオーバーライド/実装
このソースアクションでは、すべての候補がチェックリスト付きで提示されます。その後、何をオーバーライドまたは実装するかを決定できます。
インポートを整理
このソースアクションを使用してインポートを整理できます。あいまいなインポートも処理でき、その場合は、正しいものを選択するためのドロップダウンリストが表示されます。未解決の型を持つコード行も、決定を助けるために提示されます。
ゲッターとセッターを生成
すべての新しいメンバー変数に対してゲッターとセッターを一括で生成できます。クラスに複数のフィールドがある場合、ソースアクションは、アクセサーメソッドを生成するために使用するターゲットフィールドを選択するためのクイックピックを促します。
hashCode() と equals() を生成
hashCode()とequals()はデフォルトの実装で生成できます。すべての非静的メンバー変数がリストされ、チェックリストを使用して生成されたコードをカスタマイズできます。
生成されたコードをカスタマイズするための2つのオプションがあります。
- Java 7以降を使用している場合、
java.codeGeneration.hashCodeEquals.useJava7Objectsをtrueに設定すると、Objects.hashとObjects.equalsを呼び出す短いコードを生成できます。 - また、
java.codeGeneration.hashCodeEquals.useInstanceofをtrueに設定すると、Object.getClass()を呼び出す代わりにinstanceOf演算子を使用してオブジェクトの型をチェックできます。
toString() を生成
toString()メソッドを生成する新しいソースアクションがあります。すべてのメンバー変数のチェックリストでカスタマイズが可能です。
可能な限り修飾子をfinalに変更
現在のソースファイルのすべての変数とパラメーターにfinal修飾子を追加します。
例
以前
public class Clazz {
public void method(int value) {
boolean notValid = value > 5;
if (notValid) {
// do something
}
}
}
以後
public class Clazz {
public void method(final int value) {
final boolean notValid = value > 5;
if (notValid) {
// do something
}
}
}
アクセス不可能な参照を修正
このクイックフィックスは、アクセスできない参照を修正するのに役立ちます。
存在しないパッケージを作成
パッケージ名がフォルダー名と一致しない場合、ソースコードのパッケージ名を変更するか、ファイルシステム内のフォルダーを移動する(宛先フォルダーがまだ存在しない場合でも)オプションがあります。
その他のサポートされているコードアクション
VS Codeでサポートされているコードアクションのリストは増え続けており、上記には最も一般的なものだけがリストされています。その他の注目すべきサポートされているアクションには、以下が含まれますが、これらに限定されません。
- 未解決の型を作成
final修飾子を削除- 不要なキャストを削除
- 冗長なインターフェースを削除
- switchステートメントに不足しているcaseラベルを追加
- break/continueで定義にジャンプ
- 静的要素へのアクセスを修正