2017-04-06 2 views
3

Betrachten Sie den folgenden Code ein:Warum können Sie eine Klasse mit demselben Namen wie eine geschachtelte Klasse importieren?

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. 
    } 
} 

Dieser Code kompiliert fein; aber wenn Sie sich auf Calendar innerhalb Demo beziehen, beziehen Sie sich auf Demo.Calendar, nicht java.util.Calendar.

Der Import ist eindeutig redundant; aber es scheint seltsam, dass es erlaubt ist, wenn man bedenkt Sie nicht eine Klasse mit dem gleichen einfachen Namen als Top-Level-Klasse in derselben Übersetzungseinheit (pro JLS Sec 7.5.1) definiert zu importieren erlaubt:

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

class Calendar {} 

Gibt es Ein praktischer Grund, warum ein solcher Import wie im ersten Codebeispiel kein Kompilierungsfehler wäre?

+0

Es ist nicht redundant; es ist unwirksam. Mit dem gesagt, ich bin ziemlich sicher, dass dies legal ist, nur weil die Sprachspezifikation es nicht verbietet. Wahrscheinlich ist es ein Fall, der von den Sprachdesignern nicht berücksichtigt wird. – davmac

+0

Sie haben die JLS falsch gelesen. Es verbietet nicht, einen Namen zu importieren, der einer Klasse der obersten Ebene entspricht, es verbietet das Importieren eines Namens "n", wenn "die Kompilierungseinheit auch einen Typ auf oberster Ebene [sic] deklariert, dessen einfacher Name" n "ist. Das ist nicht die Situation, die du zeigst. –

+0

@LewBloch Ich verstehe den Unterschied, auf den Sie hinweisen, nicht. Kannst du bitte ein Beispiel geben, um die Unterscheidung zu demonstrieren? –

Antwort

3

Der einzige Fall, den ich mit oben kommen kann, wo man eine zweimal (oder mehr) -nested Klasse mit dem gleichen Namen wie der Import hat:

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

In diesem Fall ist das verschachtelte Calendar nicht automatisch außerhalb des Gültigkeitsbereichs der Nested Klasse sichtbar, so dass die importierte Calendar Klasse außerhalb verwendet wird, z in der useImported Methode.

Ich würde das nicht wirklich als "praktisch" bezeichnen, aber es ist einfach verwirrend, was in jedem Kontext verwendet wird und definitiv zu vermeiden ist. Es hat mich immer noch interessiert, dass dieser Fall existiert.


Ich nehme an, es ein anderer ähnlicher Fall ist:

import java.util.Calendar; 

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

class Demo2 { 
    class Calendar {} 

    static void useNested() { ... } 
} 

(wo diese Klassen sind in derselben Übersetzungseinheit). Grundsätzlich die gleiche Idee wie oben.

0

Ich nehme an, wenn Sie eine Klasse importieren, ist es im globalen Raum dieser Kompilierungseinheit sichtbar. Wenn Sie jedoch Ihre Kompilierungseinheit oder Top-Level-Klasse mit dem Import gleich benennen, stehen Sie im Grunde im Konflikt mit dem Import, und daher ist es für JVM mehrdeutig, zu wissen, welches das ist. und da es eine Klasse kompiliert, gibt es einen Fehler für den Import.

Auch wenn es in einer anderen Klasse ist, überschatten Sie den Import dort drüben. Es ist nur ähnlich in der Art wie globale Variablen auf Klassenebene und auf Methodenebene, die sie verbergen, wenn sie mit demselben Namen definiert sind.

Hoffe, das hilft.

+0

"daher wird es für JVM mehrdeutig sein" Es ist nicht mehrdeutig, man kann sich einfach nicht auf die importierte Klasse beziehen, also wird es verhindert. Es ist genau so, als würde man Dinge wie "instanceof Integer" verhindern: Es ist nicht eindeutig für die JVM, es weist wahrscheinlich nur auf einen Programmierfehler hin. –

+0

@AndyTurner - Ich erklärte, ob die JVM den Import und die Top-Level-Klassennamen in der gleichen Kompilierungseinheit zuließ. Sorry, vielleicht war ich nicht klar. –

+0

Ja, das habe ich verstanden, und ich sage, dass es nicht zweideutig ist: es ist * redundant *, genauso wie "instanceof Integer" eine redundante Art ist, 'false' zu ​​schreiben, und daher vom Compiler nicht zugelassen wird . –

Verwandte Themen