2017-04-06 21 views
3

は、次のコードを考えてみましょう:ネストしたクラスと同じ名前のクラスをインポートするのはなぜですか?

import java.util.Calendar; 

class Demo 
{ 
    class Calendar {} 

    public static void main (String[] args) { 
     // System.out.println(Calendar.DAY_OF_WEEK); // Would be an error. 
    } 
} 

このコードは、罰金コンパイルします。 CalendarDemoに記載している場合は、Demo.Calendarであり、java.util.Calendarではありません。

インポートは明らかに冗長です。しかし、あなたが(JLS Sec 7.5.1あたり)同じコンパイル単位で定義されているトップレベルのクラスと同じ単純名を持つクラスをインポートすることができていない考慮すると、それが許可されていることを奇妙に思える:

import java.util.Calendar; // error: Calendar is already defined in this compilation unit 

class Calendar {} 

があります最初のコード例のようなインポートがコンパイル時エラーではないという実用的な理由はありますか?

import java.util.Calendar; 

class Demo { 
    static class Nested { 
    static class Calendar {} 

    static void useNested() { 
     System.out.println(Calendar.class); // Demo.Nested.Calendar 
    } 
    } 

    static void useImported() { 
    System.out.println(Calendar.class); // java.util.Calendar 
    } 

    public static void main(String[] args) { 
    Nested.useNested(); 
    useImported(); 
    } 
} 

Ideone demo

この場合:インポートと同じ名前を持つ二回(またはそれ以上)-nestedクラスを持っているところ

+0

冗長ではありません。それは効果がない。これは、言語仕様がそれを禁じていないため、これが正当であると確信しています。おそらく、それは言語設計者によって考慮されないケースです。 – davmac

+0

あなたはJLSを誤読しました。トップレベルのクラスと同じ名前をインポートすることは禁止されていません。 "コンパイル単位がシンプルな名前が' n 'であるトップレベル[sic]型も宣言している場合、名前のインポートは禁止されます。それはあなたが示す状況ではありません。 –

+0

@LewBloch私はあなたが指摘している違いを理解していません。違いを実証するための例を教えてください。 –

答えて

3

私が思い付くことができる唯一のケースです入れ子になったCalendarは、Nestedクラスのスコープ外で自動的に表示されないため、インポートされたCalendarクラスは、外部で使用されます。 useImported方法では、

私は本当にこれを "実用的な"使い方とは言いませんが、各文脈でどちらが使われているのか分かりづらいです。しかし、このケースが存在することは私にはまだ興味があります。


Iは、別の同様の場合があると:

import java.util.Calendar; 

class Demo { 
    static void useImported() { ... } 
} 

class Demo2 { 
    class Calendar {} 

    static void useNested() { ... } 
} 

(これらのクラスは、同じコンパイル単位です)。基本的には上記と同じ考えです。

0

あなたがクラスをインポートすると、そのコンパイルユニットのグローバルスペースに表示されると思います。しかし、コンパイルユニットやトップレベルクラスの名前をインポートと同じにすると、基本的にインポートと矛盾します。したがって、JVMがどちらがどちらであるかを知ることはあいまいです。クラスをコンパイルして以来、インポートにエラーが発生します。

また、別のクラスの中にある場合は、そこにインポートをシャドーイングしています。グローバル/クラスレベルの変数とメソッドレベルの変数が同じ名前で定義されている場合は、それを隠すのと同じようになります。

これが役に立ちます。

+0

"したがって、JVMではあいまいになります。"あいまいではなく、単にインポートしたクラスを参照することはできません。これはちょうど '' instanceof Integer'のようなものを防ぐのと同じです:JVMにあいまいではなく、恐らくプログラマーのエラーを示しているでしょう。 –

+0

@AndyTurner - JVMがインポートとトップレベルのクラス名を同じコンパイル単位で同じものとして許可しているかどうかを仮定して説明しました。申し訳ありませんが、おそらく私は明確ではありませんでした。 –

+0

はい、私は理解していますが、曖昧ではないことを言っています:「冗長」*と同じように、「instanceof Integer」は 'false'を書き込むための冗長な方法なので、コンパイラによって許可されません。 –

関連する問題