Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
boah, du machst dir ja Gedanken,
ich kanns nicht sagen, aber dir versichern, dass andere Faktoren 99,99999% der Performance und des Speichers benötigen werden
Du bist Dir nicht klar über die Funktion des import-statements.
Um die schon genannten Punkte noch mal anders zu formulieren, das import-statement bindet lediglich einen oder mehrere Namen aus einem Paket in den aktuellen Namensraum ein, damit man weniger tippen muss. Es hat aber sonst keine Funktion.
Im Prinzip kann man Java ganz ohne import-Statements programmieren, man muss dann nur allen Namen den vollständigen Paketpfad voranstellen, also z.B. java.util.List statt einfach List verwenden. Die Klasse java.util.List wird durch das import-statement unter dem Namen "List" verfügbar gemacht, und es ist nur als Hilfe für den Programmierer gedacht.
Im compilierten Programm steht aber immer java.util.List.
Da es sich dabei nur um eine Tipphilfe handelt, soll per Definition kein Unterschied bestehen. Gäbe es einen, wäre es ja mehr als eine Tipphilfe.
Alle Klassen, die im Import von Klasse A aufgeführt sind, werden in dem Moment vom Classloader geladen, in dem die Klasse A geladen wird. Zum laden der Klasse gehört auch, dass die statischen Felder initialisiert werden und der static initializer aufgerufen wird (das ist im kompilierten Code übrigens wirklich das selbe, denn die Initialisierung von statischen Feldern wird in einen static initializer umgesetzt).
Wenn also viele Klassen geladen werden (die u.U. nicht benötigt werden, weil der Code nicht angesprungen wird) und die initialisierung länger dauert, hat man sowohl einen Performancenachteil, als auch eine höhere Last im PermSpeicher, u.U. auch im Heap.
Diese Factorymethode ist also sinnvoll:
Code:
public static CallerIF newCaller() {
if (isInServer) {
return new myServerPackage.CallerImpl();
} else {
return new myClientPackage.CallerStub();
}
}
Auf dem Server muss die Klasse CallerStub nicht vorhanden sein, auf dem Client muss CallerImpl nicht vorhanden sein. Würden die Klassen im Import stehen, gäbe es jeweils eine ClassNotFoundException bzw. ich müsste beide Implementierungen ausliefern, obwohl sie dort nie benötigt werden.
[EDIT]
Ob das bedeutet, dass myPackage.* alle Klassen dieses Packages lädt, weiß ich nicht, würde ich aber vermuten.
ACHTUNG:
Wer jetzt blind loslegt und alle Imports rausschmeißt, hat nicht verstanden wann was optimiert werden muss.
Die Regeln des Optimierens:
- optimiere spät
- optimiere spät
- optimiere spät
- optimiere nur wenn nötig, nicht auf Verdacht
- bevor du optimierst, identifiziere die Bottlenecks bzw. Speicherprobleme
- optimiere nur, wen du signifikante Verbesserungen erzielen kannst
> Alle Klassen, die im Import von Klasse A aufgeführt sind, werden in dem Moment vom Classloader geladen, in dem die Klasse A geladen wird.
hmm, gleich mal ein Test:
Code:
package test;
import test2.*;
public class Test
{
public static void main(String[] args)
{
// new Test3();
System.out.println("Ende");
}
}
--------------
package test2;
public class Test3
{
static
{
System.out.println("Hi");
}
}
bei mir erscheint nur die Ausgabe 'Ende',
ist der new-Aufruf dagegen nicht auskommentiert, dann wird auch 'Hi' ausgegeben,
wird vielleicht doch optimiert?
über die Funktion des import-statements habe ich schnell mal in der Spezifikation quergelesen. Zum Thema Einbindung von Namen in den Namensraum steht dort:
[zitat]
An import declaration allows a static member or a named type to be referred to by a simple name (§6.2) that consists of a single identifier.
[/zitat]
Also: Eine import-Deklaration erlaubt es, statische "member" oder einen "named type" unter einem einfachen Namen anzusprechen, der aus einem einzelnen "identifier" besteht. Das deckt sich glaub ich grad eben noch mit meiner Behauptung, obwohl import natürlich eine Deklaration ist, und kein Statement, wie ich gesagt hatte.
Ein Kompilat kann man sich einfach ansehen, z.B. die .class-Dateien einfach im Editor aufmachen. Es stehen dort tatsächlich die kompletten Pfadnamen drin (mit '/' anstelle von '.'). Ich habe außerdem spaßeshalber ein kleines Progrämmchen einmal mit, einmal ohne imports kompiliert, also mit absoluten Pfaden. Die entstehenden .class-Dateien sind genau gleich.
Code:
package javaapplication3;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<Integer> ll = new LinkedList<Integer>();
ll.add(1);
System.out.println("" + ll.get(0));
}
}
Und (auskommentiert, um die Zeilenanzahl nicht zu ändern):
Code:
package javaapplication3;
//import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
java.util.LinkedList<Integer> ll = new java.util.LinkedList<Integer>();
ll.add(1);
System.out.println("" + ll.get(0));
}
}
Und SlaterB's Gegenbeispiel ist auch mit import test2.Test3 anstelle von import test2.* noch ein Gegenbeispiel. Über die Funktionsweise des Classloaders weiß ich ansonsten nix.
Wie andere auch schon gesagt haben, das stimmt nicht. Ein import ist Schall und Rauch, reine Kurzschreibweise.
Nur weil Eclipse dir in der Standardeinstellung ein 'Warning' für unused imports gibt, muss es noch nicht schlecht sein.
Im übrigen gibt es auch bei Eclipse die möglich zu sagen wenn mehr als n Klassen aus einem Package importiert werden, ersetz die imports durch den .* Import.
Müsste ja dann bedeuten, dass zur Laufzeit alles durchsucht werden müsste, um Klassen zu finden, die man grundlos in den Perm-Space schaufeln will :wink:
Nach genauem Evaluieren muss ich Wildcard und Wolfram unumwunden Recht geben.
Spec lesen bildet eben ;-)
Ich habe folgendes gesehen:
1.) Mein Factory-Beispiel von oben funktioniert auch mit Imports richtig. Warum es in einer Containerumgebung nicht geklappt hatte, muss an einem anderen Umstand liegen. Wie es aussieht reproduziert mein Minimalbeispiel nicht das ClassLoader-Problem, welches mir mal vor einiger Zeit untergekommen ist.
2.) Der SUN Compiler (JDK 1.4) kompiliert alle Deklarationen (ob mit import oder vollqualifiziert) zu Imports. Werden gleiche Klassennamen aus unterschiedlichen Packages im Code vollqualifiziert verwendet, wird einfach das zuerst geparste importiert, das andere vollqualifiziert gelassen. Lustig, ist aber so ;-)
Das habe ich mir mal mit einem Decompiler angesehen... man lernt ja immer was dazu...
2.) Der SUN Compiler (JDK 1.4) kompiliert alle Deklarationen (ob mit import oder vollqualifiziert) zu Imports. Werden gleiche Klassennamen aus unterschiedlichen Packages im Code vollqualifiziert verwendet, wird einfach das zuerst geparste importiert, das andere vollqualifiziert gelassen. Lustig, ist aber so ;-)
Das habe ich mir mal mit einem Decompiler angesehen... man lernt ja immer was dazu...