Me gustaría saber la mejor forma de cargar un recurso en Java:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.
Me gustaría saber la mejor forma de cargar un recurso en Java:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.Respuestas:
Trabaja la solución de acuerdo a lo que quieras ...
Hay dos cosas que getResource
/ getResourceAsStream()
se obtiene de la clase que se llama en ...
Así que si lo haces
this.getClass().getResource("foo.txt");
intentará cargar foo.txt desde el mismo paquete que la clase "this" y con el cargador de clases de la clase "this". Si coloca una "/" al principio, está haciendo referencia absoluta al recurso.
this.getClass().getResource("/x/y/z/foo.txt")
cargará el recurso desde el cargador de clases de "this" y desde el paquete xyz (deberá estar en el mismo directorio que las clases en ese paquete).
Thread.currentThread().getContextClassLoader().getResource(name)
se cargará con el cargador de clases de contexto pero no resolverá el nombre de acuerdo con ningún paquete (debe estar absolutamente referenciado)
System.class.getResource(name)
Cargará el recurso con el cargador de clases del sistema (también tendría que estar absolutamente referenciado, ya que no podrá poner nada en el paquete java.lang (el paquete de System).
Solo eche un vistazo a la fuente. También indica que getResourceAsStream solo llama a "openStream" en la URL devuelta por getResource y lo devuelve.
Thread#setContextClassLoader
. Esto es útil si necesita modificar la ruta de clases mientras se ejecuta el programa.
Bueno, depende en parte de lo que quieras que suceda si realmente estás en una clase derivada.
Por ejemplo, supongamos que SuperClass
está en A.jar y SubClass
está en B.jar, y está ejecutando código en un método de instancia declarado en SuperClass
pero donde se this
refiere a una instancia de SubClass
. Si lo usa this.getClass().getResource()
, se verá relativo a SubClass
, en B.jar. Sospecho que normalmente eso no es lo que se requiere.
Personalmente, probablemente lo usaría con Foo.class.getResourceAsStream(name)
más frecuencia: si ya conoce el nombre del recurso que está buscando y está seguro de dónde está en relación Foo
, esa es la forma más sólida de hacerlo, en mi opinión.
Por supuesto, hay ocasiones en las que eso no es lo que quieres también: juzga cada caso por sus méritos. Es simplemente el "Sé que este recurso está incluido con esta clase" es el más común con el que me he encontrado.
this.getClass()
. Cree una instancia de la subclase y llame al método ... imprimirá el nombre de la subclase, no la superclase.
Busco tres lugares como se muestra a continuación. Comentarios bienvenidos.
public URL getResource(String resource){
URL url ;
//Try with the Thread Context Loader.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Let's now try with the classloader that loaded this class.
classLoader = Loader.class.getClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Last ditch attempt. Get the resource from the classpath.
return ClassLoader.getSystemResource(resource);
}
Sé que es muy tarde para otra respuesta, pero solo quería compartir lo que me ayudó al final. También cargará recursos / archivos desde la ruta absoluta del sistema de archivos (no solo la ruta de clases).
public class ResourceLoader {
public static URL getResource(String resource) {
final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
classLoaders.add(Thread.currentThread().getContextClassLoader());
classLoaders.add(ResourceLoader.class.getClassLoader());
for (ClassLoader classLoader : classLoaders) {
final URL url = getResourceWith(classLoader, resource);
if (url != null) {
return url;
}
}
final URL systemResource = ClassLoader.getSystemResource(resource);
if (systemResource != null) {
return systemResource;
} else {
try {
return new File(resource).toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}
}
private static URL getResourceWith(ClassLoader classLoader, String resource) {
if (classLoader != null) {
return classLoader.getResource(resource);
}
return null;
}
}
Probé muchas formas y funciones que se sugirieron anteriormente, pero no funcionaron en mi proyecto. De todos modos he encontrado una solución y aquí está:
try {
InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
img = ImageIO.read(path);
} catch (IOException e) {
e.printStackTrace();
}
this.getClass().getResourceAsStream()
en este caso. Si echa un vistazo a la fuente del getResourceAsStream
método, notará que hace lo mismo que usted, pero de una manera más inteligente (alternativa si no ClassLoader
se puede encontrar en la clase). También indica que puede encontrarse con un potencial null
en getClassLoader
su código ...
this.getClass().getResourceAsStream()
no me funciona, así que lo uso. Creo que hay algunas personas que pueden afrontar un problema como el mío.