The difference between class.getResourceAsStream and class.getClassLoader().getResourceAsStream

1. Basic use:

Create a configuration file classloaderResource.properties for data reading, and a test class GetResourceTest
insert image description here

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class GetResourceTest {
    
    
    public static void main(String[] args) throws IOException {
    
    
        InputStream inputStream = GetResourceTest.class
                .getResourceAsStream("classloaderResource.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        properties.list(System.out); //遍历输出
    }
}

insert image description here

Two usages:
1: class name.class.getClassLoader().getResourceAsStream("file name") | generally a file in the form of key-value, such as .properties
2: class name.class.getResourceAsStream("file name")

2. The difference between the two methods

1: Class name.class.getClassLoader() is equivalent to reading from the classpath;
2: Class name.class.getResourceAsStream("file name") reads from the path where the current class is located.

Scene1: The classloaderResource.properties file is placed in the root directory:
insert image description here

classname.class.getClassLoader() needs to be read using the following code

InputStream inputStream = GetResourceTest.class.getClassLoader()
        .getResourceAsStream("classloaderResource.properties");

Whereas using classname.class.getResourceAsStream("filename") would require

InputStream inputStream = GetResourceTest.class.getClassLoader()
        .getResourceAsStream("/classloaderResource.properties");

Scene2: When the classloaderResource.properties file is placed in the package:
insert image description here
classname.class.getClassLoader() needs to be read using the following code (starting with the first layer of package name under src)

InputStream inputStream = GetResourceTest.class.getClassLoader()
    .getResourceAsStream("JavaTest/classloader/classloaderResource.properties");     

Whereas using classname.class.getResourceAsStream("filename") would require

InputStream inputStream = GetResourceTest.class
        .getResourceAsStream("classloaderResource.properties");

Step on the pit

Today, I created a new module under this project, and then created a new json file under the gson package of the module. I can’t read it with the above method, and NullPointerException is abnormal! The json file can be read by moving it to the resources folder, ah, this, could it be that the above-mentioned mode can only be normal under this project (non-Module)? Therefore, non-java files are uniformly placed in the resources directory (subfolders will not report errors) to reduce unnecessary errors.
insert image description here

basic understanding

Both are used to obtain the input stream of resource files under the classpath path.

Why classpath instead of src, because when the web project is running, the IDE compiler will move some resource files under src to WEB-INF/classes, and the classPath directory is actually the classes directory. This directory generally contains class files and resource files (xml, properties...) when the web project is running;

In addition, when using springboot for development, its default directory is not WEB-INF but BOOT-INF, but its meaning is the same. Specifically as shown in the figure below:

img

In the picture above, the blue box is the content in the classpath, that is, the code actually written by myself, and the dependent code is mainly in the lib directory.

From another perspective, the changes in the directory where the file is located before and after compilation

Before compiling:

img

After compilation:

img

class refers to the class object of the current class, getClassLoader() is to obtain the current class loader, what is a class loader? To put it simply, it is used to load java classes. The class loader is responsible for loading the class file into memory, and creating an instance of the java.lang.Class class, which is the class object, and the class loader for each class are not the same. getResourceAsStream(path) is used to obtain resources, and the class loader obtains resources from the classPath by default, because there are class files below, so this code generally means to obtain resources in the classPath directory through the class loader .and in stream form.

We know that all classes in Java are loaded into the virtual machine through loaders, and there is a parent-child relationship between class loaders, that is, the child knows the parent, and the parent does not know the child, so the types loaded by different children are Inaccessible (although they are all placed in the method area), so loading resources through the loader of the current class here is guaranteed to be loaded by the same loader as the class type.

difference

1. class.getClassLoader().getResourceAsStream(String name)

By default, the file is found from the classpath (the file is placed in the resources directory), and the name cannot contain "/", otherwise a null pointer will be thrown

eg:

InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("gamvanclub.cfg.xml");

2. class.getResourceAsStream(String name)

Find the resource by the given name, the rule of querying the resource is implemented by the class load of the given class, this method is executed by the loader of the class; if this class is loaded by bootstrap, then the method is executed by the ClassLoader.getSystemResourceAsStream agent.

Before proxying, the absolute resource name is constructed through the following algorithm of the incoming name parameter:

If name starts with "/", then the absolute path is the name followed by /

eg:

//从classpath下的config相对路径中读取config.ini"
mypackage.Hello.class.getResourceAsStream("/config/config.ini");

If the name does not start with "/", then the absolute path is the package name "." and then add the name after replacing it with "/".

eg:

//com.abc.App就是/com/abc/App/name 或者写作 : ../../name(以class所在路径为基准,文件相对于该类的路径)

Java class loading process

3 steps:

1. Load, load the binary file of the class.

2. Links:

(1) Verify that the structure of the bytecode is correct

(2) Prepare, allocate space to static members and assign default values ​​(note here: the first assignment of static variables is carried out when the class is loaded, and it is not the same process as the custom assignment at the time of subsequent initialization, that is Static members may have been assigned twice during initialization)

(3) Parsing, turning symbolic references into direct references

3 Initialization, giving static members their own given initial values

The order in which classes are instantiated:

(1) Initialization and execution of static members, methods and static code blocks

(2) Initialization and execution of ordinary members, methods, and ordinary code blocks

(3) Execution of the constructor (the constructor of the parent class is executed first)

Guess you like

Origin blog.csdn.net/qq_43842093/article/details/130663768