java中Class.getResourceAsStream()和ClassLoader.getResourceAsStream()的区别
简介
Class.getResourceAsStream()和ClassLoader.getResourceAsStream()方法都是从项目中读取文件,但很容易被搞混。
ClassLoader
public class Client2 {
  public static void main(String[] args) {
    //从classpath下查询
    InputStream in = Client2.class.getClassLoader().getResourceAsStream("files/asd.txt");
    if (in == null) {
      return;
    }
    try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
      String line = null;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

我们将文件放到classpath下,ClassLoader会直接从classpath的根目录下查找文件,
输出结果为
this is a test file2
Class
public class Client3 {
  public static void main(String[] args) {
    InputStream in = Client3.class.getResourceAsStream("/files/asd.txt");
    if (in == null) {
      return;
    }
    try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
      String line = null;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
通过Class也可以读到classpath下的文件,我们需要以/开头。
public class Client4 {
  public static void main(String[] args) {
    InputStream in = Client4.class.getResourceAsStream("abc.txt");
    if (in == null) {
      return;
    }
    try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
      String line = null;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

我们将文件放到当前类所在的包下,这个时候不能以/开头,直接相对路径就可以。
源码分析
public final
    class Class<T> implements java.io.Serializable,
                              java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {
	public InputStream getResourceAsStream(String name) {
        	name = resolveName(name);
        	ClassLoader cl = getClassLoader0();
        	if (cl==null) {
            		// A system class.
            		return ClassLoader.getSystemResourceAsStream(name);
        	}
   		//实际上还是调用ClassLoader的getResourceAsStream()方法
        	return cl.getResourceAsStream(name);
    	}
	//解析文件路径,如果以/开头,截取/之后的,不以/开头,当做相对路径,添加包的路径
	private String resolveName(String name) {
        	if (name == null) {
            		return name;
        	}
        	if (!name.startsWith("/")) {
            		Class<?> c = this;
            		while (c.isArray()) {
                		c = c.getComponentType();
           		}
            		String baseName = c.getName();
            		int index = baseName.lastIndexOf('.');
            		if (index != -1) {
                		name = baseName.substring(0, index).replace('.', '/')
                   		 +"/"+name;
            		}
       		} else {
            		name = name.substring(1);
        	}
        	return name;
    }
}
总结
ClassLoader从classpath下查询,不能以/开头,不能相对路径,Class如果以/开头,直接截取/之后的路径,不以/开头,转换成包含package的全路径,内部还是调用的ClassLoader的方法。
 
         
         
         
         
         
        
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号