2009-05-13 2 views
1

Erstens bin ich kein Java-Typ, aber ich stieß auf etwas, das auf der Oberfläche als eine Inkonsistenz mit der Art und Weise erscheint, wie Importe funktionieren.Implementierung von Importen

Sagen Sie eine Datei und in dieser Datei haben Sie Ihre Hauptfunktion und Sie haben festgelegt, auch eine Klasse Foo, jetzt eine andere Implementierung von Foo existiert auch in einem Paket. Angenommen, Sie möchten beide Versionen in Ihrer Funktionalität verwenden.

Sie können Foo nicht explizit aus dem Paket importieren, d. H. import mypackage.Foo;

Da dies zu einem Konflikt mit der lokal in der Datei definierten Klasse führt, wird bei der Kompilierung ein Fehler generiert.

Was Sie können tun ist das gesamte Paket importieren, d. H. import mypackage. *;

Dies funktioniert und Sie Foo unter Verwendung der vollständig qualifizierten Namen zugreifen können, führen den einfachen Namen mit in der Verwendung der lokal Foo. Die Inkonsistenz, die ich sehe, ist, dass, während ersteres einen Fehler erzeugt (Sie haben eine Klasse importiert und der einzige Zweck des Imports darin besteht, den einfachen Namen im Gegensatz zum voll qualifizierten Namen verwenden zu können), führt letzteres nicht einmal zu a Warnung.

Ich hätte gedacht, dass beide Fälle eine Warnung generieren würden, dh Sie könnten die falsche Klasse verwenden, da sie an zwei Stellen definiert ist, oder die Importanweisung ist redundant, da die Verwendung des einfachen Namens in die lokal definierte Klasse aufgelöst wird nicht die importierte.

Also meine Frage ist: Gibt es einen Grund, warum es auf diese Weise implementiert ist?

Ja, es ist ein Ausreißer Fall, das verstehe ich.

+1

kleiner Hinweis: Die import-Anweisung wird nur verwendet, so dass Sie den Paketnamen nicht eingeben müssen, es tut nichts anderes, es ist nur eine Verknüpfung. Wenn Sie immer den vollständig qualifizierten Namen verwenden, brauchen Sie überhaupt keine Importe. –

+0

Ich verstehe, warum Pakete existieren, es ist nur, dass es inkonsistent scheint, auf eine Klasse in einem importierten Paket verweisen zu können und überhaupt keine Warnungen zu haben - unabhängig davon, ob eine Klasse mit diesem Namen lokal definiert ist oder nicht wenn Sie explizit versuchen, eine Klasse mit demselben Namen wie einem lokal definierten zu importieren. In beiden Fällen ist die Import-Anweisung für diese Klasse redundant, aber die eine gibt Fehler und die andere tut nichts. – Stinomus

Antwort

9

Sie können auf Foo zugreifen, indem Sie den vollqualifizierten Namen auch ohne Importieren von mypackage verwenden. *;

Über Warnungen: Es ist nichts Gefährliches passiert, denke ich. Sie verwenden nichts mehrdeutiges.

+0

Es ist mehr, dass die lokal definierte Klasse stille Präferenz im letzten Beispiel hat - Sie würden erwarten, dass das Verhalten des vorherigen Beispiels damit übereinstimmt, da in beiden Fällen der Import redundant ist. – Stinomus

+0

Wenn es eine Warnung über nicht verwendeten/redundanten Import geben würde, würden alle Zusammenstellungen plötzlich mit Hunderten von Warnungen spammen. Und auch, niemand schreibt heutzutage von Hand Importe. – alamar

+0

Gut ungenutzte und redundante sind nicht wirklich das Gleiche. Gibt es viele Fälle, in denen Sie ein Paket mit einer darin enthaltenen Klasse importieren, die denselben Namen wie eine Ihrer lokal definierten Klassen hat? – Stinomus

1

importieren Sie mypackage. * Könnte für all die anderen Dinge, die in meinem Paket sind, notwendig sein. Wenn es eine Warnung gäbe, wäre es schwer, sie überhaupt zu vermeiden, d. H. Sie müssten alle anderen Klassen, die Sie von meinem Paket verwenden, vollständig qualifizieren. Noch schlimmer, bedenken Sie den Fall, wenn Version 1 von mypackage nicht Foo enthielt, also gab es keinen Konflikt und daher auch keinen Grund, eine Warnung auszugeben. Version 2 enthält Foo, aber natürlich ist es nicht das Foo, auf das du in deinem Programm zugreifen willst. Wenn daher der Compiler vor den Konflikten "import package. *" Warnt, wird "import package. *" Potenziell weniger aufwärtskompatibel.

3

Wie die obige Antwort sagt, tut der Import effektiv nichts in Bezug auf die Foo in dem anderen Paket; unabhängig davon, ob Sie importieren oder nicht, können Sie nicht beziehen sich auf diese andere Foo über den kurzen Klassennamen und Sie können verweisen über einen voll qualifizierten Klassennamen.

Konzeptionell können Sie sich import mypackage.* nicht unbedingt als "importieren Sie alle Klassen von mypackage", aber vielleicht "importieren Sie alle nicht in Konflikt stehenden Klassen von mypackage". Ich weiß nicht, wie die Compiler-Implementierung von Sun es tut, aber es könnte definitiv entscheiden, mypackage.Foo nicht als Teil des Platzhalters zu finden (und somit überhaupt nicht zu importieren) und der Code würde genauso funktionieren.

Importieren ist wirklich nur ein Alias ​​von kurzen Klassennamen zu voll qualifizierten Klassennamen einrichten (z. B. wenn ich sage Date interpretiere das als java.util.Date). Es ist zu erwarten, dass Sie eine Warnung erhalten, wenn Sie etwas tun, das völlig redundant ist, wie zum Beispiel das Importieren nur der in Konflikt stehenden Klasse. Allerdings, wenn Sie ein ganzes Paket mit * ziehen, würde es mir scheinen falsch für den Compiler zu beschweren, dass einer der Klassennamen kollidiert; das würde in der Praxis so oft passieren und zu 99% der Zeit harmlos sein, dass es ein "Junge, der Wolf rief" -Syndrom bis zu dem Punkt erzeugen würde, an dem du weniger auf diese und andere Warnungen achten würdest, seit du gewöhne dich daran, mit ihnen bombardiert zu werden.

Übrigens, wenn Sie sowohl java.util.* als auch java.sql.* importieren, ist dies zulässig und führt an sich nicht zu Warnungen; Aber wenn Sie dann versuchen, nur auf Date (ohne eine solche Klasse in Ihrem lokalen Paket) verweisen, erhalten Sie einen Kompilierungsfehler, da der Name nicht eindeutig ist.

+2

Die JVM tut nichts mit Importen; intern verwendet es immer vollständig qualifizierte Klassennamen. Importe sind nur für den Compiler relevant. –

+2

Importe sind meistens für den Entwickler relevant, da Sie beim Importieren einer Klasse auf den Kurznamen verweisen und sich dadurch Tipparbeit ersparen können. – duffymo

+0

Gibt es einen Grund, warum sie nicht beide zum selben Verhalten führen sollten? – Stinomus

1

Sie können sich "Import p. *" Vorstellen, was bedeutet "wenn Sie einen Namen in der aktuellen Datei nicht auflösen können, versuchen Sie es in Paket p aufzulösen". Der Compiler importiert nicht alles in p an dem Punkt, an dem die Importanweisung angezeigt wird. Stattdessen wird in p (und anderen in den import ... * -Anweisungen genannten Paketen) gesucht, wenn ein Name gefunden wird, der in der unmittelbaren Kompilierungseinheit nicht aufgelöst werden kann.