Me pregunto cuál es la diferencia entre Class.getResource()
y ClassLoader.getResource()
.
editar: especialmente quiero saber si hay algún almacenamiento en caché a nivel de archivo / directorio. Como en "¿se almacenan en caché las listas de directorios en la versión Class?"
AFAIK lo siguiente esencialmente debería hacer lo mismo, pero no lo son:
getClass().getResource()
getClass().getClassLoader().getResource()
Descubrí esto al jugar con un código de generación de informes que crea un nuevo archivo WEB-INF/classes/
desde un archivo existente en ese directorio. Al usar el método de Class, pude encontrar archivos que estaban allí durante el despliegue usando getClass().getResource()
, pero al tratar de recuperar el archivo recién creado, recibí un objeto nulo. Navegar por el directorio muestra claramente que el nuevo archivo está allí. Los nombres de los archivos se anteponen con una barra diagonal como en "/myFile.txt".
La ClassLoader
versión de, getResource()
por otro lado, encontró el archivo generado. Según esta experiencia, parece que hay algún tipo de almacenamiento en caché de la lista del directorio. ¿Tengo razón, y si es así, dónde está documentado?
De los documentos de API enClass.getResource()
Encuentra un recurso con un nombre de pila. El cargador de clases definitorias de la clase implementa las reglas para buscar recursos asociados con una clase determinada. Este método delega al cargador de clases de este objeto. Si este objeto fue cargado por el cargador de clases bootstrap, el método delega a ClassLoader.getSystemResource (java.lang.String).
Para mí, esto dice "Class.getResource realmente está llamando a getResource () de su propio cargador de clases". Lo cual sería lo mismo que hacer getClass().getClassLoader().getResource()
. Pero obviamente no lo es. ¿Podría alguien proporcionarme alguna iluminación sobre este asunto?
fuente
Class.getResource
puede tomar un nombre de recurso "relativo", que se trata en relación con el paquete de la clase. Alternativamente, puede especificar un nombre de recurso "absoluto" utilizando una barra diagonal. Las rutas de recursos del cargador de clases siempre se consideran absolutas.Entonces, los siguientes son básicamente equivalentes:
Y así son estos (pero son diferentes de los anteriores):
fuente
this.getClass().getClassLoader().getResource("/");
devolver nulo? No debería ser lo mismo quethis.getClass().getClassLoader().getResource(".");
La primera llamada busca en relación con el
.class
archivo, mientras que la última busca en relación con la raíz de classpath.Para depurar problemas como ese, imprimo la URL:
fuente
getClassLoader().getResource("/...")
siempre regresanull
: el cargador de clases no elimina el inicio/
de la ruta, por lo que la búsqueda siempre falla. SologetClass().getResource()
maneja un inicio/
como una ruta absoluta relativa a la ruta de clase.Tuve que buscarlo en las especificaciones:
Class.getResource (recurso de cadena)
ClassLoader.getResource (recurso de cadena)
Clase getResource () - la documentación establece la diferencia:
fuente
Todas estas respuestas por aquí, así como las respuestas en esta pregunta , sugieren que cargar URL absolutas, como "/foo/bar.properties", se trata de la misma manera por
class.getResourceAsStream(String)
yclass.getClassLoader().getResourceAsStream(String)
. Este NO es el caso, al menos no en mi configuración / versión de Tomcat (actualmente 7.0.40).Lo siento, no tengo ninguna explicación satisfactoria, pero supongo que Tomcat hace trucos sucios y su magia negra con los cargadores de clases y causa la diferencia. Siempre lo usé
class.getResourceAsStream(String)
en el pasado y no he tenido ningún problema.PD: también publiqué esto aquí
fuente
Class.getResources
recuperaría el recurso por el cargador de clases que carga el objeto. MientrasClassLoader.getResource
recuperaría el recurso usando el cargador de clases especificado.fuente
Intenté leer desde input1.txt que estaba dentro de uno de mis paquetes junto con la clase que intentaba leerlo.
Los siguientes trabajos:
La parte más importante fue llamar
getPath()
si desea el nombre de ruta correcto en formato de cadena. NO UTILICEtoString()
porque agregará texto de formato adicional que TOTALMENTE ARRIBA el nombre del archivo (puede probarlo y ver la impresión).Pasé 2 horas depurando esto ... :(
fuente
FileReader
oFileInputStream
no se puede usar para acceder a ellos. La respuesta no es correcta.