Ich frage mich, was der Unterschied zwischen Class.getResource()
und ist ClassLoader.getResource()
.
Bearbeiten: Ich möchte insbesondere wissen, ob es sich um Caching auf Datei- / Verzeichnisebene handelt. Wie in "Werden Verzeichnislisten in der Klassenversion zwischengespeichert?"
AFAIK die folgenden sollten im Wesentlichen das gleiche tun, aber sie sind nicht:
getClass().getResource()
getClass().getClassLoader().getResource()
Ich habe dies entdeckt, als ich mit Code zur Berichterstellung herumgespielt habe, der eine neue Datei WEB-INF/classes/
aus einer vorhandenen Datei in diesem Verzeichnis erstellt. Bei Verwendung der Methode aus Class konnte ich Dateien finden, die bei der Bereitstellung vorhanden getClass().getResource()
waren. Beim Versuch, die neu erstellte Datei abzurufen, wurde jedoch ein Nullobjekt empfangen. Das Durchsuchen des Verzeichnisses zeigt deutlich, dass die neue Datei vorhanden ist. Den Dateinamen wurde ein Schrägstrich wie in "/myFile.txt" vorangestellt.
Die ClassLoader
Version von hat getResource()
andererseits die generierte Datei gefunden. Aus dieser Erfahrung geht hervor, dass die Verzeichnisliste zwischengespeichert wird. Habe ich recht und wenn ja, wo ist das dokumentiert?
Aus der API - Dokumentation aufClass.getResource()
Findet eine Ressource mit einem bestimmten Namen. Die Regeln für die Suche nach Ressourcen, die einer bestimmten Klasse zugeordnet sind, werden vom definierenden Klassenlader der Klasse implementiert. Diese Methode wird an den Klassenladeprogramm dieses Objekts delegiert. Wenn dieses Objekt vom Bootstrap-Klassenladeprogramm geladen wurde, delegiert die Methode an ClassLoader.getSystemResource (java.lang.String).
Für mich lautet dies "Class.getResource ruft wirklich getResource () seines eigenen Klassenladeprogramms auf". Welches wäre das gleiche wie zu tun getClass().getClassLoader().getResource()
. Aber es ist offensichtlich nicht. Könnte mir bitte jemand etwas Licht in diese Angelegenheit bringen?
quelle
Class.getResource
kann einen "relativen" Ressourcennamen annehmen, der relativ zum Paket der Klasse behandelt wird. Alternativ können Sie einen "absoluten" Ressourcennamen mithilfe eines führenden Schrägstrichs angeben. Classloader-Ressourcenpfade gelten immer als absolut.Das Folgende ist also grundsätzlich gleichwertig:
Und so sind diese (aber sie unterscheiden sich von den oben genannten):
quelle
this.getClass().getClassLoader().getResource("/");
null zurückgeben? Es sollte nicht dasselbe sein wiethis.getClass().getClassLoader().getResource(".");
Der erste Aufruf sucht relativ zur
.class
Datei, während der letztere relativ zum Klassenpfadstamm sucht.Um solche Probleme zu beheben, drucke ich die URL:
quelle
getClassLoader().getResource("/...")
kehrt immer zurücknull
- der Klassenladeprogramm entfernt den führenden nicht/
aus dem Pfad, sodass die Suche immer fehlschlägt. NurgetClass().getResource()
Griffe einen Start/
als absoluter Pfad relativ zu dem Classpath.Musste es in den Spezifikationen nachschlagen:
Class.getResource (String-Ressource)
ClassLoader.getResource (String-Ressource)
Die getResource () - Dokumentation der Klasse gibt den Unterschied an:
quelle
Alle diese Antworten hier sowie die Antworten in dieser Frage legen nahe, dass das Laden absoluter URLs wie "/foo/bar.properties" von
class.getResourceAsStream(String)
und gleich behandelt wirdclass.getClassLoader().getResourceAsStream(String)
. Dies ist NICHT der Fall, zumindest nicht in meiner Tomcat-Konfiguration / Version (derzeit 7.0.40).Entschuldigung, ich habe absolut keine befriedigende Erklärung, aber ich denke, dass Tomcat schmutzige Tricks und seine schwarze Magie mit den Klassenladern macht und den Unterschied verursacht. Ich habe es
class.getResourceAsStream(String)
in der Vergangenheit immer benutzt und hatte keine Probleme.PS: Ich stellte auch dies über hier
quelle
Class.getResources
würde die Ressource vom Klassenladeprogramm abrufen, das das Objekt lädt. WhileClassLoader.getResource
würde die Ressource mit dem angegebenen Klassenladeprogramm abrufen.quelle
Ich habe versucht, aus input1.txt zu lesen, das sich in einem meiner Pakete befand, zusammen mit der Klasse, die versucht hat, es zu lesen.
Folgendes funktioniert:
Der wichtigste Teil war das Aufrufen,
getPath()
wenn Sie den richtigen Pfadnamen im String-Format wünschen. NICHT VERWENDEN,toString()
da dadurch zusätzlicher Formatierungstext hinzugefügt wird, der den Dateinamen vollständig angibt (Sie können es versuchen und den Ausdruck sehen).Verbrachte 2 Stunden damit, dies zu debuggen ... :(
quelle
FileReader
oderFileInputStream
nicht zugangs sie verwendet werden können. Die Antwort ist nicht richtig.