[For beginners] Where to review when a class cannot be found at compile time

Target audience of the article

When I thought about compiling and executing Java commands by myself, Write the source code, create a folder hierarchy, place the source code, and so on. When it comes to compiling with the javac command

"Cannot find symbol"

Isn't it possible that you can't create a class file forever because of this one line? Since syntax errors provide relatively detailed information, it is easy to identify the cause. Regarding the error that the class cannot be found, the correction points are different depending on the implementation content, so There is no such thing as "If you fix this, it will be fixed!"

But what a beginner really needs is It is not information that can be used only in individual cases such as "how to fix" It can be reused as "the cause can be understood by looking here due to the mechanism" I think it's debugging knowledge.

This time, when I studied the mechanism around compilation, for "I can't find the symbol" I've come to see how to approach it, so I would like to introduce my debugging procedure at this time.

Viewpoint 1: Does the class name match?

The scratches should be shallow. As a result of conducting a grand survey from the perspective of introducing it later, It's too painful on a day when the cause of the error was just a typing mistake, First of all, is the declaration of the Test.java class `` `public class Tst``` (an example)? I suspect a typing mistake. Except for class declaration and package specification, syntax errors will occur. I don't chase that far.

Viewpoint 2: What is the type of class?

The type here is the class that cannot be found Whether it is a ** bootstrap class ** or a ** class stored in a ** jar file ** Is it a ** user class **?

If you want to know more about bootstrap class and user class, Find out about Java classloaders and compile-time type lookup.

I'll skip the details here and give you a rough introduction.

--Bootstrap class Core features such as the frequently used java.lang package, such as the core API of the JDK, are included here. --User class This class is created by the user (programmer). Also called a user-defined class. --Class stored in jar file There are various third-party libraries, user-defined libraries, etc. It is the one that is often added to the build path with eclipse.

What can be judged here is the class that cannot be found In the case of bootstrap class, set "Java environment variable that specifies JDK" In the case of user classes, you should suspect "classpath variables".

I can't tell if it's a bootstrap class. In that case, refer to Core API Document.

If the bootstrap class is not found

Since the JDK has not been specified, the environment variable "JAVA_HOME" is Let's review whether it is set properly. There are many articles on how to set JAVA_HOME, so I will omit it.

If the class in the jar file is not found

Specifying the classpath in the jar file is slightly different from specifying the classpath in the class file. However, the only difference is whether you specify a directory or the jar file itself. Let's check if the command syntax is correct.

#For jar
$ javac -classpath /lib/example-lib.jar Example.java
#For class files
$ javac -classpath /lib Example.java

If the user class cannot be found

In this case, there are a few more perspectives to look at. If this is the case, please continue reading the following content.

Viewpoint 3: Is the classpath specified correctly?

Loading user classes and third-party libraries The classpath must be specified correctly in both rabbits and corners, If you don't understand the mechanism of classpath specification properly, it won't work.

Below, we will introduce the viewpoints when reviewing the classpath. You do not have to investigate in the order of introduction.

Viewpoint 3-1: Is the package route specified?

Other than that, it was pushed by other explanations and ignored. The fact that "if you specify a package hierarchy in your classpath, it will not be imported successfully". I guess it's too obvious to be written, but I got caught here.

What it means is that there is the following folder structure, and in UseCommons.java Suppose you are importing `` `com.example.util``` because you want to use StrFactory. スクリーンショット 2020-05-25 16.25.32.png

UseCommons.java


package com.example.util;

In the above case, src is recognized as the package root, com ~ app is recognized as the package hierarchy, and so on. What I did when compiling these

#The current directory is/src
$ javac -classpath /src/com/example/util com/example/app/UseCommons.java

As mentioned above, by specifying `` `/ src / com / example / utilin the classpath, I wanted to compile UseCommons.java by loading the classes under util. However, Java follows the package hierarchy starting from the directory specified by the classpath **, so With the above settings, when UseCommons.java goes to StrFactory.java,/src/com/example/util/com/example/util```I will go to see it.

In other words, the correct classpath would be: with src, the package root.

#The current directory is/src
$ javac -classpath /src com/example/app/UseCommons.java

From the above point of view, with the package root specified in the -classpath option In the place where the contents of the import statement declared in the class file are concatenated Let's check if the class you want to load is placed.

Viewpoint 3-2: Is the default setting disabled?

I think this is the best songwriter. What was set by default is overwritten by specifying options etc. If the necessary settings are disabled, it is difficult to notice because you are not usually aware of it.

-Classpath is usually set to ". (Current directory)". With that in mind, take a look at the example below. スクリーンショット 2020-05-25 16.16.19.png

Initially, it had the above configuration, so you can compile it normally with the following command.

#The current directory is/src
$ javac com/example/app/UseCommons.java

However, after this, use the external library "commons-lang3-3.10.jar" in UseCommons.java. I decided to use it, and changed the folder structure as follows. スクリーンショット 2020-05-25 17.00.46.png Then, when I added the commons library to the classpath and executed the following command, I get an error that StrFactory cannot be found.

#The current directory is/src
$ javac -classpath /lib/commons-lang3-3.10.jar com/example/app/UseCommons.java

This is the default setting of the classpath option ". (The current directory in the example is / src)" This is because Java can no longer search for classes under src due to overwriting. Therefore, if you modify the above command as follows, the error will be resolved.

#The current directory is/src
$ javac -classpath /lib/commons-lang3-3.10.jar:. com/example/app/UseCommons.java

At the end

That's the compile-time debugging perspective I can have today. I think there are various other perspectives, so it's just for beginners to study. I hope you will recognize it as a help for the first step. The broader the perspective, the better, so I would like to deepen my learning.

Also, I wrote about Java compilation in another article, so If you are interested in how compilation works, please also refer to the following articles.

Link to the article: [Introduction to Java Commands Chapter 3 Compiling Source Code](https://qiita.com/maple_syrup/items/c0aa2eacb8f486dc52a8#%E7%AC%AC%EF%BC%93%E7%AB% A0-% E3% 82% BD% E3% 83% BC% E3% 82% B9% E3% 82% B3% E3% 83% BC% E3% 83% 89% E3% 82% 92% E3% 82% B3 % E3% 83% B3% E3% 83% 91% E3% 82% A4% E3% 83% AB% E3% 81% 99% E3% 82% 8B)

Recommended Posts

[For beginners] Where to review when a class cannot be found at compile time
A review note for the class java.util.Scanner
A review note for the class java.util.Optional
A review note for the class java.util.Objects
[Ubuntu] What to do when MongoDB cannot be started due to a SocketException error
A memo to do for the time being when building CentOS 6 series with VirtualBox
Things to watch out for when creating a framework
[Spring Boot] How to create a project (for beginners)
What to do when Git Repository cannot be displayed in Team Explorer for Eclipse in Azure