user3882271
user3882271

Reputation:

Java files with cyclic imports

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

Answers (2)

roger
roger

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

duffymo
duffymo

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

Related Questions