Java静的インポート
-
12-11-2019 - |
質問
実験様では、Java以外の静的メソッドが静的コンテキストでもスコープの同じ名前のメソッドをすべてオーバーライドすることを発見しました。パラメータの過負荷を許可せずにさえ。のように
import java.util.Arrays;
import static java.util.Arrays.toString;
public class A {
public static void bar(Object... args) {
Arrays.toString(args);
toString(args); //toString() in java.lang.Object cannot be applied to (java.lang.Object[])
}
}
.
仕様でこれについて何も見つかりません。これはバグですか?そうでなければ、そのような言語を実装する理由はありますか?
UPD:Java 6この例をコンパイルしないでください。質問は、なぜですか?
解決
説明は簡単ではありませんが、行動は非常に意図的ではないという事実は変わりません:
呼び出される方法を解決するときは、コンパイラが正しい名前のメソッドを持つ最小の囲み範囲を見つけることです。その後、オーバーロード解像度やゲームでのCOのような他のものがあります。
今ここで起こっているのは、toString()
メソッドを含む最小の囲み範囲がClass Aであるため、Object
から継承するクラスAです。したがって我々はそこをやめて、より遠くに検索しません。 SADLERY NEXTコンパイラは、特定の範囲内のメソッドの最善の適合を検索し、それがそれらのいずれかを呼び出すことができず、エラーを与えることを試みます。
オブジェクトのメソッドと同じ名前の名前を持つ静的インポートメソッドは、の静的インポート(JLS)よりも優先されます。方法のシャドウイングを詳細に説明していますが、この問題のために、それを覚えているだけではるかに簡単だと思います)。
編集: @alf ピクチャ全体を望んでいる方のメソッド呼び出しを説明します。それはかなり複雑ですが、問題は単純ではありませんので予想されます。
他のヒント
オーバーライドではありません。それがうまくいった場合、this.toString()
は、オーバーライドが発生した場合のように、A
の代わりにArrays.toString
のメソッドにアクセスします。
言語仕様静的インポートはstatic
メソッドと型の解像度にのみ影響します。
CシャドウのフィールドをインポートするパッケージPのコンパイル単位Cの単一静的インポート宣言Dは、Cの静的インポートオンデマンド宣言で宣言されたnの宣言。
パッケージPのコンパイル単位Cの単一静的インポート宣言Dは、署名Sの宣言をインポートする任意の静的メソッドという名前のの宣言をインポートしました。 C、C全体を通して、Cにおける静的インポートオンデマンド宣言
パッケージPのコンパイル単位C内の単一静的インポート宣言D:N Shadowsという名前のタイプをインポートする
- 任意の静的タイプ c。で静的インポートオンデマンド宣言でインポートされたnという名前。
- 任意のトップレベルタイプ(7.6)p。の別のコンパイルユニット(§7.3)で宣言されています。
- タイプは、cでタイプインポートオンデマンド宣言(§7.5.2)でインポートされたn という名前のタイプ。 cを通してc。
静的インポートは、非静的なメソッドや内部の種類をシャドウしません。
だから
toString
は非静的な方法をシャドウしません。toString
という名前はA
の非静的メソッドを参照することができますので、static
のArrays
メソッドを参照することはできません。そのメソッドは引数を取り出すことができないので、コンパイルエラーが発生します。セクション15.12.1 解決策と、
toString
メソッド内ではなく、toString
メソッド内では使用できません。を完全に書き換える必要があります。私の推測は、言語デザイナーがメソッドの解決ルールを簡単に保持したいということです。つまり、同じ名前は、
String toString()
メソッドに表示されているかどうかが同じことを意味することを意味します。 / P>
次のようにしてみてください コードでがではなく、コンパイラエラーを取得する
.
import static java.util.Arrays.sort;
public class StaticImport {
public void bar(int... args) {
sort(args); // will call Array.sort
}
}
このコンパイルとあなたのものが該当する理由は、オブジェクトの親がクラスの親であるため、依然としてtoString()
(またはクラスオブジェクトで定義されている他のメソッド)がオブジェクトクラスにスコープされていることです。したがって、コンパイラがオブジェクトクラスからそれらのメソッドのマッチングシグネチャを見つけると、コンパイラエラーが発生します。オブジェクトクラスにはsort(int[])
メソッドがないため、コンパイラは static import と一致しています。
私はそれがバグであること、または通常の輸入とは異なるものではありません。たとえば、インポートされたものと同じ名前のプライベートクラスがある場合は、インポートされたものは反映されません。