IntelliJ IDEA 2020.3 ヘルプ

パラメーターの導入

パラメーターの導入リファクタリングでは、新しいパラメーターをメソッドに抽出できます。

関数型パラメーターの抽出リファクタリングを使用することもできます。この場合、IntelliJ IDEA は選択されたコードを分析し、抽出されたフラグメントのメソッドシグネチャーが何であるかを調べ、このメソッドシグニチャを持つすべての機能インターフェースを見つけ出し、選択されたインターフェースに基づいてコードフラグメントを匿名クラスにラップし、パラメーター。

  1. エディターで、パラメーターとして導入する式内にキャレットを配置します。

  2. Ctrl+Alt+P を押すか、メインメニューからリファクタリング | 抽出 | パラメーターを選択します。機能パラメーターを抽出する場合は、Ctrl+Alt+Shift+P を押すか、メインメニューからリファクタリング | 抽出 | 関数型パラメーターを選択します。

  3. パラメーターの名前を指定し、パラメーターの導入ポップアップで必要なオプションを選択します。例: 既存のメソッド呼び出しを変更したくない場合は、オーバーロードメソッドによる委譲チェックボックスを選択します。

  4. 必要なら、Shift+Tab を押して新しいパラメーターの型を変更します。(このステップでパラメーター名の編集に戻りたい場合は、Tab を押します。)

パラメーターの例を抽出する

新しいパラメーターを抽出するときは、既存のメソッドにパラメーターを導入するか、オーバーロードメソッドによる委譲オプションを使用して元のメソッドを保存し、パラメーターで新しいメソッドを定義します。

メソッド generateText () の文字列値 "Hello, World!" を新しいパラメーター text に置き換えましょう。値 "Hello, World!" は、更新されたメソッド呼び出し generateText("Hello, World!") のメソッドに渡されます。

public class HelloWorldPrinter { public static void print() { System.out.println(generateText()); } private static String generateText() { return "Hello, World!".toUpperCase(); } }
public class HelloWorldPrinter { public static void print() { System.out.println(generateText("Hello, World!")); } private static String generateText(String text) { return text.toUpperCase(); } }
object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(): String { return "Hello, World!".toUpperCase() } }
object HelloWorldPrinter { fun print() { println(generateText("Hello, World!")) } private fun generateText(text: String): String { return text.toUpperCase() } }

今度はオーバーロードメソッドによる委譲を使いましょう。この場合、新しいオーバーロードメソッドが作成され、このメソッドの定義で新しいパラメーターが抽出されます(2 番目の generateText() メソッド)。既存の generateText() メソッドのシグネチャーは変更されません。ただし、メソッド自体は変更されています。今度は、新しい generateText() メソッドを呼び出し、この呼び出しで値 "Hello, World!" を渡します。 generateText() の既存の呼び出し(メソッド print())は変更されません。

public class HelloWorldPrinter { public static void print() { System.out.println(generateText()); } private static String generateText() { return "Hello, World!".toUpperCase(); } }
public class HelloWorldPrinter { public static void print() { System.out.println(generateText()); } private static String generateText() { return generateText("Hello, World!"); } private static String generateText(String text) { return text.toUpperCase(); } }
object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(): String { return "Hello, World!".toUpperCase() } }
// if you selected the "Introduce default value" option object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(text: String = "Hello, World!"): String { return text.toUpperCase() } }

機能パラメーターの例

Hello.printHello() 内の System.out.println(s); でリファクタリングを実行しましょう。

IntelliJ IDEA は、適切なメソッドシグネチャー (String) -> void を持つすべての機能インターフェースを検索し、そのうちの 1 つを選択することを提案します。(この例では、インターフェース Person が選択されています。)

その結果、選択されたフラグメント System.out.println(s); は、インターフェース Person に基づく匿名クラスでラップされます。この匿名クラスは、printText() 内の printHello() の呼び出しにパラメーターとして渡されます。

Person はパラメーターとして printHello() に追加され、最初に選択されたコードフラグメントは、インターフェース sayHello() のメソッドの呼び出しに置き換えられます。

@FunctionalInterface public interface Person { public void sayHello (String s); } public class Hello { private void printHello () { String s="Hello"; System.out.println(s); } private void printText () { printHello(); } }
@FunctionalInterface public interface Person { public void sayHello (String s); } public class Hello { private void printHello(Person person) { String s = "Hello"; person.sayHello(s); } private void printText () { printHello(new Person() { public void sayHello(String s) { System.out.println(s); } }); } }

パラメーターの導入リファクタリングに関する特別な注意

  • メソッド宣言でフィールドを新しいパラメーターとして提供する場合、メソッド呼び出しでこのフィールドはクラスインスタンスのフィールドとして表示されます。

  • クラスメンバーがアクセスできない場合(たとえば、上記の例ではフィールドは private です)、メソッド呼び出しに挿入されますが、このファイルをコンパイル不能にするエラーとしてハイライトされます。

  • getter のパラメーターを導入を使用してフィールドをリファクタリングする場合は、拡張ダイアログが表示されます。このダイアログには、オプショングループ式で使用されているフィールドを getter で置換しますがあります。
    • 置換しない : どのフィールドも getter の呼び出しに置き換えられません。

    • コンテキストのアクセスできないフィールドを置換する : 使用状況のコンテキストから直接アクセスできないフィールドのみが getter の呼び出しに置き換えられます。

    • すべてのフィールドを置換 : すべてのフィールドは getter への呼び出しに置き換えられます。

  • リファクタリングをローカル変数に適用すると、パラメーターの導入ダイアログボックスに追加のチェックボックスが表示されます。
    • 出現箇所をすべて置換 (<number_of_occurrences> 回の出現) : 有効にすると、選択した変数のすべての出現箇所がパラメーターに置き換えられ、変数定義を削除するチェックボックスが有効になります。それ以外の場合は、選択された変数の使用箇所のみがパラメーターに置き換えられます。

    • 変数定義を削除する : 有効にすると、変数定義は削除されます。

    • パラメーターの初期化に変数初期化子を使用する : 有効にすると、変数イニシャライザを使用してメソッド呼び出しのパラメーターを初期化します。

副次作用

パラメーターの導入リファクタリングを使用すると、実際のメソッドパラメーターであるクラスインスタンスまたは式に適用すると、予期しない副作用が発生する可能性があります。たとえば、そのようなコードの場合:

class AClass { int field; int method() { return field; } } class Usage { void method(List list) { int sum = 0; for(Iterator it = list.iterator(); it.hasNext(); ) { sum += ((AClass) it.next()).method(); } } }

フィールド field に適用されたリファクタリング後のコード:

class AClass { int field; int method(int newfield) { return newfield; } } class Usage { void method(List list) { int sum = 0; for(Iterator it = list.iterator; it.hasNext(); ) { sum += ((AClass) it.next()).method(((AClass) it.next()).field); } } }

反復子の値は 2 倍に増えます。これは実際に期待する動作ではありません。

ただし、IntelliJ IDEA は一時変数を正常に使用して、インクリメント / デクリメント / 代入操作や新しいキーワードの使用状況を解決できます。例:

public int myMethod(List list) { return list.size(); } public void anotherMethod() { myMethod(new ArrayList()); }

リファクタリング後の同じコードは次のようになります。

public int myMethod(List list, int newPar) { return list.size(); } public void anotherMethod() { final ArrayList list = new ArrayList(); myMethod(list, list.size()); }

新しい変数 list が作成され、この変数を使用してメソッド呼び出しに使用されるすべてのパラメーターが提供されます。