Java'da bir kaynak yüklemenin en iyi yolunu bilmek istiyorum:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.
Java'da bir kaynak yüklemenin en iyi yolunu bilmek istiyorum:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.Yanıtlar:
Çözümü istediğiniz şeye göre çalışın ...
Çağrıldığı sınıftan alacağı getResource
/ getResourceAsStream()
alacağı iki şey var ...
Yani eğer yaparsan
this.getClass().getResource("foo.txt");
foo.txt dosyasını "this" sınıfıyla aynı paketten ve "this" sınıfının sınıf yükleyicisiyle yüklemeye çalışır. Önüne bir "/" koyarsanız, o zaman kesinlikle kaynağa atıfta bulunuyorsunuz.
this.getClass().getResource("/x/y/z/foo.txt")
kaynağı "this" sınıf yükleyicisinden ve xyz paketinden yükler (bu paketteki sınıflarla aynı dizinde olması gerekir).
Thread.currentThread().getContextClassLoader().getResource(name)
bağlam sınıfı yükleyici ile yüklenecek, ancak adı herhangi bir pakete göre çözümlemeyecektir (kesinlikle referans verilmelidir)
System.class.getResource(name)
Kaynağı sistem sınıfı yükleyiciyle yükleyecektir (java.lang paketine (Sistem paketi) hiçbir şey koyamayacağınız için kesinlikle başvurulması gerekir.
Sadece kaynağa bir bakın. Ayrıca getResourceAsStream'in getResource'tan döndürülen URL'de yalnızca "openStream" i çağırdığını ve bunu döndürdüğünü belirtir.
Thread#setContextClassLoader
. Bu, program çalışırken sınıf yolunu değiştirmeniz gerekirse kullanışlıdır.
Eh, kısmen sen eğer ne istediğinizi bağlıdır aslında türetilmiş bir sınıfta.
Örneğin, SuperClass
A.jar'da olduğunu ve B.jar'da olduğunu ve SubClass
içinde bildirilen SuperClass
ancak burada this
bir örneğini ifade eden bir örnek yönteminde kod çalıştırdığınızı varsayalım SubClass
. Eğer kullanırsanız this.getClass().getResource()
kavramaya göre bakacağız SubClass
B.jar içinde. Sanırım genellikle gerekli olan bu değil.
Şahsen muhtemelen Foo.class.getResourceAsStream(name)
en sık kullanırdım - peşinde olduğunuz kaynağın adını zaten biliyorsanız ve bunun neresine göre olduğundan eminseniz, Foo
IMO'yu yapmanın en sağlam yolu budur.
Elbette , istediğiniz şeyin bu olmadığı zamanlar da vardır: her vakayı kendi yararına göre değerlendirin. Karşılaştığım en yaygın kaynak sadece "Bu kaynağın bu sınıfla birlikte olduğunu biliyorum".
this.getClass()
. Alt sınıfın bir örneğini oluşturun ve yöntemi çağırın ... üst sınıfın değil, alt sınıfın adını yazdıracaktır.
Aşağıda gösterildiği gibi üç yeri araştırıyorum. Yorumlar hoş geldiniz.
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);
}
Başka bir cevap için çok geç olduğunu biliyorum ama sonunda bana yardımcı olan şeyi paylaşmak istedim. Ayrıca, dosya sisteminin mutlak yolundan da kaynakları / dosyaları yükleyecektir (yalnızca sınıf yollarının değil).
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;
}
}
Yukarıda önerilen birçok yolu ve işlevi denedim, ancak projemde işe yaramadı. Her neyse, bir çözüm buldum ve işte burada:
try {
InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
img = ImageIO.read(path);
} catch (IOException e) {
e.printStackTrace();
}
this.getClass().getResourceAsStream()
Bu durumda kullanmalısın . getResourceAsStream
Yöntemin kaynağına bir göz atarsanız, sizden aynı şeyi yaptığını ancak daha akıllıca ( ClassLoader
sınıfta hiç bulunamıyorsa geri dönüş) yaptığını fark edeceksiniz . Ayrıca kodunuzda bir potansiyel null
ile karşılaşabileceğinizi de gösterir getClassLoader
…
this.getClass().getResourceAsStream()
için çalışmıyor, bu yüzden işe yarıyor kullanıyorum. Sanırım benimki gibi sorunlarla yüzleşebilecek bazı insanlar var.