Class Files and Compilation in Java
A resource is data a program uses that is not code, such as images, sounds, and text; the user normally does not need to know where it is stored.
Why Programs Carry Extra Files
Most beginning Java programs consist only of code, so it is natural to think of a program as a collection of classes and nothing else. Real programs often carry other material along with their code. A picture may be shown on screen, a sound may be played during a game, and a block of text may be read at startup. Java calls this kind of material a resource.
The learner using the program normally sees the picture or hears the sound without ever thinking about the file that holds it. That gap between what the user sees and where the data actually lives is the reason resources need a dedicated lookup mechanism. This article follows one running example, the image file cards.png, which a card program uses. Keep one question in mind as you read: when the program asks for cards.png, what has to be true about where that file is stored for the request to succeed?
What do you think happens?
The program asks for cards.png using only the file name, with no folder path. What does the program need to finish the request?
Reveal answer
It needs a ClassLoader, the object that performs the search and knows where to look for the file.
The code never states a folder path or drive letter. The lookup supplies only the file name, so whatever makes the file findable has to come from the object that performs the search.
What Counts as a Resource
A resource is data a program uses that is not code, such as images, sounds, and text. The user normally does not need to know where it is stored.
- Images, such as a picture shown on screen (the
cards.pngfile in this article's running example) - Sounds, such as a sound played during a game
- Text, such as a block of text read at startup
The defining feature is the word not in the definition. A class file contains code the program runs, while a resource is material the program uses while running. Both live alongside the program, but a resource is only read and used, and it is found through the same search mechanism that finds class files.
Tracing the Two-Line Lookup
The first thing a program does with a resource is ask for it. The lookup for cards.png takes two lines. Before reading the explanation, look at the pattern below and predict what the program needs in order to finish the request. The sections that follow explain each part.
ClassLoader loader = getClass().getClassLoader();
URL url = loader.getResource("cards.png");- 1Line 1 obtains a ClassLoader through the current object's class and stores it in a variable named loader.
- 2Line 2 passes the file name
cards.pngto that ClassLoader by callinggetResource, and stores the returned URL in a variable named url. - 3The program never opens a folder itself. It delegates the search to the ClassLoader and receives a URL in return.
getClass()gives the class of the current objectgetClassLoader()returns the ClassLoader associated with that classgetResource("cards.png")hands only the file name to the ClassLoader- The result is stored in a variable of type URL
Notice what the code does not contain. There is no folder path and no drive letter. The file name is the only information the program gives. The lookup works because the ClassLoader already knows which locations to search, and that knowledge comes from the class path, which the next section describes.
Read the diagram from top to bottom. The program first obtains the ClassLoader, then sends the file name. The ClassLoader checks the class path locations, and if the file is found there, the request returns a URL to the program. The program then uses that URL and never needs to know the folder where cards.png is stored.
The ClassLoader and the Class Path
A ClassLoader is an object that finds class files and resource files by searching the class path. In Java it is represented by an object of type ClassLoader. Its everyday job is to find and load class files, and it can also find resource files that sit in the same kinds of places. Because a single object handles both, a resource request does not need its own separate search system.
The ClassLoader answers one question: where should I look? Everything it can find, it finds by checking a fixed set of locations that it was given. Those locations are the class path.
The class path is the list of locations searched. It generally includes the standard classes location and the current directory. If the program is packaged in a jar file, the jar file is also on the class path. A resource is only findable if the file sits in one of these searched locations.
Where a Lookup Fails
The lookup depends entirely on the class path. Because of that, most failures come from a mismatch between where the file is stored and where the ClassLoader searches. The decision below shows the single point at which a request either succeeds or fails.
On the yes branch the request succeeds, and the program receives the URL it asked for. On the no branch the file is not on any searched location, so the lookup does not locate it. The source does not describe the exact result the program receives on that branch, so check how your program handles a missing result when you write code that depends on a resource.
Common mistake Assuming the file is found because it sits in the same project folder as the code
What it looks likecards.png is placed in a folder that is not among the class path locations
Why it failsThe ClassLoader only searches the locations it was given through the class path, so a file outside those locations is not searched.
Do this insteadConfirm that the file is in one of the searched locations, such as the standard classes location, the current directory, or the jar file if the program is packaged in one.
Common mistake Putting a folder path in the file name passed to getResource
What it looks likegetResource("images/cards.png") when the file sits directly in a searched location
Why it failsThe lookup supplies only the file name and relies on the class path for location, so a path that does not match a searched location will not succeed.
Do this insteadPass the file name as the lookup expects and make sure the file sits in a location the class path covers.
Common mistake Forgetting that a packaged program changes the search locations
What it looks likeA program is moved into a jar file, but the resource is left in a folder outside the jar
Why it failsThe jar file is part of the class path when the program is packaged in one, so the resource needs to be in a location the packaged program actually searches.
Do this insteadCheck where the resource ends up after packaging, and make sure the search locations used by the packaged program include it.
Practice: Trace a New Resource
A program needs a sound file named hit.wav during a game. Using the same two-line pattern as cards.png, write the two lines that request hit.wav. Then describe, step by step, what the ClassLoader does with the file name, and state the one condition under which the request succeeds.
Hints
- Only the file name goes into
getResource, just as withcards.png. - Think about the ClassLoader as the object that answers where should I look.
- The success condition is about whether hit.wav sits in one of the searched locations on the class path.
Key Takeaways
- A resource is data a program uses that is not code, such as images, sounds, and text, and the user normally does not need to know where it is stored.
- A program requests a resource with two lines: it obtains a ClassLoader through the current object's class, then calls
getResourcewith only the file name, receiving a URL in return. - The ClassLoader is the object that finds class files and resource files by searching the class path, which lists the locations searched, including the standard classes location and the current directory, plus the jar file if the program is packaged in one.
- A resource lookup fails when the file is not on a searched location, because the search depends entirely on the class path and not on where the code happens to sit.