ホームページ  >  記事  >  Java  >  Javaの可変長パラメータリストの解析と使用上の注意点

Javaの可変長パラメータリストの解析と使用上の注意点

高洛峰
高洛峰オリジナル
2017-01-19 15:13:041497ブラウズ

Java変数パラメータ一覧

class A {}

すべてのクラスはObjectを継承しているため、Object配列をパラメータとして取れるメソッド:

public class parameter {
  static void printArray(Object[] args){
    for(Object obj : args){
      System.out.print(obj + " ");
    }
    System.out.println();
  }
   
  public static void main(String[] args){
    printArray(new Object[] {
        new Integer(47), new Float(3.14), new Double(11.11)
    });
    printArray(new Object[]{"one", "two", "there"});
    printArray(new Object[]{new A(), new A(), new A()});
  }
}

機能が追加されたJava SE5以降のバージョンの場合は、次のように記述できます:

public class parameter {
  public static void printArray(Object... args){
    for(Object obj : args){
      System.out.print(obj + " ");
    }
    System.out.println();
  }
   
  public static void main(String[] args){
    printArray(new Integer(47), new Float(3.14), new Double(11.11));
    printArray(47, 3.14F, 11.11);
    printArray("one", "two", "three");
    printArray(new A(), new A(), new A());
    printArray((Object[]) new Integer[]{1, 2, 3, 4});
    printArray();
  }
}

オブジェクトが考えるパラメータリストを使用できます:

public class VarargType{
  static void f(Character... args){
    System.out.print(args.getClass());
    System.out.println(" length " + args.length);
  }
   
  static void g(int... args){
    System.out.print(args.getClass());
    System.out.println(" length " + args.length);
  }
   
  public static void main(String[] args){
    f('a');
    f();
    g(1);
    g();
    System.out.println(" int [] " + new int[0].getClass());
  }
}

これはJava 5で導入された機能です。メソッドが受け取るパラメータの数が不確実な場合、この機能は役に立ちます。

たとえば、IO 操作が関係する場合、入力と出力の少なくとも 2 つのストリームを閉じる必要があります。これにより、ストリームを閉じる操作を次のメソッドにカプセル化して、1 回の呼び出しで複数のストリームを閉じることができます。

public static void closeSilent(Closeable... closeables) {
   for (Closeable closeable : closeables) {
     if (closeable != null) {
        try {
          closeable.close();
        } catch (IOException ignored) {
        }
     }
   }
}

この機能が使用に適していると思われる唯一の場所です。次の特徴があります:

これらのパラメータは同じタイプです
パラメータの数は不確かで、それぞれはオプションです。これらのパラメータの目的はすべて同じです。たとえば、上記はすべて実行シャットダウンです。
Java 可変長パラメーター リストは、メソッド パラメーター リストの最後にのみ配置できます。

Java可変長パラメータリストの実装

Java可変長パラメータリストの実装は、これらのパラメータを配列にカプセル化してコンパイラに渡すことです。

たとえば、上記のメソッドのシグネチャは実際には closeSilent(Closeable[] closeables) void です。

罠に入る

AとBの2か所で呼び出されるメソッドがあります。9月にAにパラメータを追加する必要がありました。その時、頭がおかしくなって可変長を使うことにしましたパラメータリストはBだと思いました。単純に変更する必要はなく、穴が埋められているだけです。

最近、B にここで 2 つの新しいパラメーターを追加し、メソッドのパラメーター リストにパラメーターを追加し続けるように依頼しました。これらのパラメーターの型は異なるため、可変長パラメーター リストはオブジェクト型として宣言されます。

最初の落とし穴は、このメソッドで可変長パラメータの要素を取得する際に、一部のパラメータが渡されていないことが考慮されず、そのまま配列オフサイド例外が発生してしまうことです。すぐに可変長パラメータリストは良くないと感じたので、それは必要なく、通常の固定形式パラメータの受け渡しに変更しました。

修正後、テスト環境でテストしたところ問題はありませんでした。本番環境でいくつかのクラスを置き換えた後、エラーが報告され、メソッドが見つかりませんでした。メソッドのシグネチャを見ると、配列のままであり、置き換えられていませんでした。ソースコードから判断すると、呼び出し先を変更する必要はなく、テスト環境が完全にパッケージ化されているため、問題なく置き換えられるとは思っていませんでした。

メソッドのシグネチャはコンパイル中に決定されます。ソース コードを変更する必要がないと思われるからといって、コンパイルされたクラスを置き換える必要がないわけではありません。

実は、今回の変則契約の場合、ソースコード内の定数の値を変更した後、その定数を定義しているクラスファイルのみが置き換えられ、その定数を参照しているクラスファイルはすべて置き換えられると聞いたことがあります。再編集しないと、不可解な問題が発生します。これは本質的にメソッド署名の状況と同じ問題です。

Java の可変長パラメーター リストの解析と使用時の注意事項に関するその他の関連記事については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。