Reputation:
I am trying to understand how javac
deals with cyclic imports. After few attempts, I got the below code to be compiled:
package com.test.p1;
import com.test.p2.ClassP2;
public class ClassP1 {
public static void main(String[] args) {
System.out.println("ClassP1 loaded");
ClassP2.testP2();
}
}
And
package com.test.p2;
import com.test.p1.ClassP1;
public class ClassP2 {
public static void testP2() {
System.out.println("ClassP2 loaded");
}
}
When I compiled ClassP2.java
first, I was expecting it to fail as ClassP1.java
was not yet compiled and no class
file was generated. Yet, it compiled ok, and generated ClassP2.class
and ClassP1.class
. Running ClassP1 worked fine as well.
Now my question is how did javac
generate class file for ClassP1 when I only compiled ClassP2. And why does this not happen when cyclic reference is not there - i.e. when ClassP2 imports ClassP1, but ClassP1 does not import ClassP2 ?
I am still new to Java and trying to understand how compilation works.
Upvotes: 7
Views: 4581
Reputation: 26
It is not a result of cyclic imports, it is a result of importing ClassP1 in ClassP2.java and javac
being able to find the source for ClassP1 based on the arguments you passed to javac
and the location from which you executed the command.
See the -sourcepath option in the docs for javac:
-sourcepath sourcepath Specify the source code path to search for class or interface definitions. As with the user class path, source path entries are separated by semicolons (;) and can be directories, JAR archives, or ZIP archives. If packages are used, the local path name within the directory or archive must reflect the package name. Note: Classes found through the class path may be subject to automatic recompilation if their sources are also found. See Searching For Types.
Upvotes: 0
Reputation: 308948
There's nothing cyclic going on here. It sounds like you, along with a lot of other people, confuse import with class loading.
All the import statement does is allow you to use the short name to refer to a Java class in your code:
import java.sql.ResultSet;
public V find() {
ResultSet rs = null; // You can type ResultSet instead of java.sql.ResultSet
}
The import statement won't help you if the short name is ambiguous (e.g. java.util.Date
and java.sql.Date
in the same class).
The byte code for java.sql.ResultSet
is not loaded into the JVM until your code needs it at runtime.
Upvotes: 4