2016-05-15 4 views
2

ClassLoaderを使用すると、これらの2つのケースが異なる動作をする理由がわかりません。誰かが、ClassLoaderが検索をどのように変更して、なぜそれがJarファイルへの完全なパスを必要とするように変更するのかを説明できますか?.jarリソースをロードするときにClassLoaderを使用する

package com.example; 
import java.io.InputStream; 

public class SomeClass { 
    private static InputStream stm; 
    static { 
    for (final String s : new String[] { "file.png", "com/example/file.png", "/com/example/file.png" }) { 
     // case 1 - w/o classLoader 
     stm = SomeClass.class.getResourceAsStream(s); 
     System.out.println("w/o   : " + (stm == null ? "FAILED to load" : "loaded") + " " + s); 

     // case 2 - w/ classLoader 
     stm = SomeClass.class.getClassLoader().getResourceAsStream(s); 
     System.out.println("w/classloader: " + (stm == null ? "FAILED to load" : "loaded") + " " + s); 
    } 
    } 

    public static void main(final String args[]) {} 
} 

が生成されますパスはあなたが呼んでgetResourceAsStream()方法に応じて異なる評価され

w/o   : loaded file.png 
w/classloader: FAILED to load file.png 
w/o   : FAILED to load com/example/file.png 
w/classloader: loaded com/example/file.png 
w/o   : loaded /com/example/file.png 
w/classloader: FAILED to load /com/example/file.png 
+0

あなたが見ている動作は意図的です。これについては、[Class.getResourceのドキュメント](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getResource-java.lang.String- )および[ClassLoader.getResource](https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html#getResource-java.lang.String-)を参照してください。 – VGR

+0

@VGR Class.getResources()は、/を先頭にして/と修飾パッケージ名/名前を使用するので、file.pngはcom/example/file.pngになり、com/example/file.pngはcom/example/com/exampleになります。 /file.pngなので、1番目と2番目の文字列の結果は意味を持ち、/com/example/file.pngはcom/example/file.pngになります。しかし、classLoaderは、 "このメソッドは、リソースの親クラスローダを最初に検索します。"という文を誤解しない限り、w/o出力と一致するはずです。それはなぜですか? – simpleuser

+0

ClassLoader.getResource: "リソースの名前は、リソースを識別する' '/' 'で区切られたパス名です。 "'/'で区切られた一連のパスコンポーネントだけが先頭にはありません。 – VGR

答えて

4

ので。あなたはクラスcom.example.SomeClassClass.getResourceAsStream()を呼び出す場合
、そのパスは、それが/で起動しない場合は、比較的SomeClassに評価され、そうfile.png/com/example/file.pngなり、com/example/file.png/com/example/com/example/file.pngとなっています。
あなたはそのClassLoaderClassLoader.getResourceAsStream()を呼び出した場合、パスは暗黙のうちに絶対的であると/で始めることはできませんので、file.png/file.pngなり、com/example/file.png/com/example/file.pngになります。
/com/example/file.pngのような絶対パスを使用する場合は、Classメソッドを使用する必要があります。

残念ながらClassLoader.getResourceAsStream()のこの暗黙の絶対性は、唯一それがそのClassLoaderのメソッドに委譲する前に、先頭のスラッシュを取り除きと述べClass.getResourceAsStream()の文書、暗黙的に記載されています。

+0

ありがとう、それはちょっと意味があります。しかし、私は/com/example/file.pngを使って試してみましたが、これはあなたのやり方にぴったり合わないfile.pngだけを使用した場合と同じように動作しました。つまり、classLoaderを使わずに作業した絶対パスであり、classLoaderを使用すると失敗しました。 – simpleuser

+1

正しくない。 '/'で始まる引数は、ClassLoader.getResourceに対して決して有効ではありません。そのメソッドへのすべての引数は、暗黙的に絶対パスです。 – VGR

+0

おかげでVGR、私はこれについての嘘つき、特にこれについての嘘つきであることを忘れてしまった。 @ user1663987私は正しい情報を与えるために私の答えを更新しました。 – Vampire

関連する問題