2009-05-13 9 views
1

まず、私はJavaの男ではありませんが、輸入の仕方と矛盾することが表面に現れました。輸入の実施

は、あなたがファイルを持っており、このファイルにあなたがあなたの主な機能を持っていて、今はFooの異なる実装はまた、パッケージ内に存在するFooのは、クラスをも定義していると言います。あなたの機能で両方のバージョンを使いたいとします。

Fooをパッケージから明示的にインポートすることはできません。import mypackage.Foo;

これは、ファイル内でローカルに定義されたクラスと競合するため、コンパイル時にエラーが生成されるためです。

あなたはです。は、パッケージ全体をインポートします。つまり、import mypackage。*;

これは動作します、あなたは地元のはFooの使用になります単純な名前を使用して、完全修飾名を使用してはFooにアクセスすることができます。 私が見ている不一致は、前者がエラーを生成している間に(あなたがクラスをインポートしており、インポートの唯一の目的は、完全修飾名ではなく単純名を使用できることです)、後者は警告。

私は、2つの場所で定義されているように間違ったクラスを使用している可能性があり、単純な名前を使用するとローカルに定義されたクラスに解決されるため、輸入されたものではありません。

私の質問です:このように実装されている根本的な理由はありますか?

はい、それは外れ値の場合です、私はそれを理解しています。

+1

little note:インポートステートメントは、パッケージ名を入力しないためにのみ使用されます。それ以外は何もしません。これは単なるショートカットです。常に完全修飾名を使用する場合、インポートはまったく必要ありません。 –

+0

私はパッケージが存在する理由を理解しています。インポートされたパッケージ内のクラスを参照し、その名前のクラスがローカルで定義されているかどうかにかかわらず、警告を全く持たないローカルに定義されたクラスと同じ名前のクラスを明示的にインポートしようとすると、 どちらの場合も、import文はそのクラスに対して冗長ですが、一方はyieldとerror、他方は何もしません。 – Stinomus

答えて

9

mypackage。*をインポートしなくても完全修飾名を使用してFooにアクセスできます。

警告について:何も危険なことは起こっていないと思います。あいまいなものは使用していません。

+0

ローカル定義されたクラスは、後者の例ではサイレントプリファレンスを持っています。前者の例の動作は、両方ともインポートが冗長であるため、これと一貫していると考えられます。 – Stinomus

+0

未使用/冗長インポートに関する警告が表示された場合、すべてのコンパイルで何百もの警告がスムーズに迷惑メールになります。 また、最近誰も手作業で輸入しているわけではありません。 – alamar

+0

まあ使用されておらず、冗長なものは実際には同じものではありません。ローカルに定義されたクラスの1つと同じ名前のクラスを持つパッケージをインポートする多くのケースがありますか? – Stinomus

1

インポート・マイパックには、他のすべてのものが必要な場合があります。警告があった場合、それを避けるのは難しいでしょう。つまり、あなたはmypackageから使用する他のクラスを完全に修飾する必要があります。 さらに、mypackageのバージョン1にFooが含まれていないため、矛盾がなく、したがって警告を出す理由もありませんでした。バージョン2にはFooが含まれていますが、プログラムでアクセスしたいのはFooではありません。 したがって、コンパイラが "import package。*"の衝突について警告すると、 "import package。*"の潜在的な上位互換性が低下する可能性があります。

3

上記の回答によれば、他のパッケージのFooに関するインポートは効果的に何もしません。あなたがインポートしているかどうかに関係なく、にできません。短いクラス名で他のFooを参照してください。は完全修飾クラス名で参照してください。

概念的に、あなたは「mypackageからすべての非競合したクラスをインポート」「mypackageからの輸入は、すべてのクラス」として必ずしもimport mypackage.*と思う、おそらくすることができます。私はSunのコンパイラ実装がどのようにそれを行うのか分かりませんが、ワイルドカードの一部としてmypackage.Fooをマッチさせないようにすることができます(したがってインポートすることもありません)。

インポートは、実際には(私が言うとき、例えばDateがあることjava.util.Dateとして解釈)を完全修飾クラス名の短いクラス名から別名を設定しています。矛盾するクラスだけをインポートするなど、完全に冗長なものを行うと警告が表示されることが予想されます。しかし、*でパッケージ全体を引っ張っているなら、コンパイラがクラス名の1つが衝突すると不平を言うのは間違っているようです。これは実際には非常に頻繁に起こり、時間の99%以上は無害です。あなたがこれらの警告や他の警告に注意を払う可能性が低いほど、「狼男の叫び声」症候群を引き起こすでしょうちょうどそれらに砲撃されるのに慣れます。

ちなみに、java.util.*java.sql.*の両方をインポートすると、これは許可され、それ自体が警告につながるわけではありません。 Date(そのようなクラスがローカルパッケージにない)を参照しようとすると、名前があいまいなのでコンパイルエラーが発生します。

+2

JVMはインポートをまったく実行しません。内部的には、常に完全修飾クラス名を使用します。インポートはコンパイラにのみ関係します。 –

+2

インポートはほとんどの場合開発者に関係します。なぜなら、クラスをインポートすることによって、その短い名前で参照することができ、入力を省くことができるからです。 – duffymo

+0

両方とも同じ動作になるべきではない理由はありますか? – Stinomus

1

"import p。*"は、 "現在のファイルで名前を解決できない場合は、パッケージpで解決してください"と考えることができます。コンパイラは、pにあるすべてのものをimportステートメントが参照される時点でインポートしません。代わりに、p(およびimport ... *ステートメントで指定された他のパッケージ)が、即時コンパイル単位で解決できない名前を見つけたら調べます。