I have this directory c:\abcd
it has no files in it, but has a subdirectory efgh.
C:\abcd>dir
Volume in drive C has no label.
Volume Serial Number is B411-D580
Directory of C:\abcd
02/08/2014 06:57 PM <DIR> .
02/08/2014 06:57 PM <DIR> ..
02/08/2014 07:01 PM <DIR> efgh
0 File(s) 0 bytes
3 Dir(s) 1,990,201,344 bytes free
The efgh subdirectory, as you can see, has 3 files. Blah.java
, Greeter.java
and comb.java
Blah.java
has a class, Greeter.java
has a class.
comb.java
happens to contain the code of Blah.java
and Greeter.java
, so it has two classes. It's superfluous but it's to demonstrate something. Which is a case of comb compiling while one of the individual files (Blah.java
) does not.
C:\abcd>cd efgh
C:\abcd\efgh>dir
Volume in drive C has no label.
Volume Serial Number is B411-D580
Directory of C:\abcd\efgh
02/08/2014 07:01 PM <DIR> .
02/08/2014 07:01 PM <DIR> ..
02/08/2014 07:00 PM 130 Blah.java
02/08/2014 07:00 PM 216 comb.java
02/08/2014 07:00 PM 99 Greeter.java
3 File(s) 445 bytes
2 Dir(s) 1,990,201,344 bytes free
These are the contents of the three files
C:\abcd\efgh>type Blah.java
package efgh;
class Blah {
Greeter greeter = new Greeter();
public static void main(String[] args) {}
}
C:\abcd\efgh>type Greeter.java
package efgh;
class Greeter {
public static void main(String[] args) {}
}
C:\abcd\efgh>type comb.java
package efgh;
class Blah {
Greeter greeter = new Greeter();
public static void main(String[] args) {}
}
class Greeter {
public static void main(String[] args) {}
}
C:\abcd\efgh>javac comb.java
So, comb.java compiles.
I see it produced Blah.class
and Greeter.class
which is further proof that it compiled, but I'll now delete those .class
files. As that makes my point, that javac comb.java
works.
C:\abcd\efgh>dir
Volume in drive C has no label.
Volume Serial Number is B411-D580
Directory of C:\abcd\efgh
02/08/2014 07:02 PM <DIR> .
02/08/2014 07:02 PM <DIR> ..
02/08/2014 07:02 PM 341 Blah.class
02/08/2014 07:00 PM 130 Blah.java
02/08/2014 07:00 PM 216 comb.java
02/08/2014 07:02 PM 261 Greeter.class
02/08/2014 07:00 PM 99 Greeter.java
5 File(s) 1,047 bytes
2 Dir(s) 1,990,201,344 bytes free
C:\abcd\efgh>del *.class
Now I'll compile them individually. And it doesn't work so well.. compiling Blah.java
gives an error.
C:\abcd\efgh>dir
Volume in drive C has no label.
Volume Serial Number is B411-D580
Directory of C:\abcd\efgh
02/08/2014 07:03 PM <DIR> .
02/08/2014 07:03 PM <DIR> ..
02/08/2014 07:00 PM 130 Blah.java
02/08/2014 07:00 PM 216 comb.java
02/08/2014 07:00 PM 99 Greeter.java
3 File(s) 445 bytes
2 Dir(s) 1,990,201,344 bytes free
C:\abcd\efgh>javac Greeter.java
C:\abcd\efgh>javac Blah.java
Blah.java:5: error: cannot find symbol
Greeter greeter = new Greeter();
^
symbol: class Greeter
location: class Blah
Blah.java:5: error: cannot find symbol
Greeter greeter = new Greeter();
^
symbol: class Greeter
location: class Blah
2 errors
I know that technically, my classpath isn't set right. Because, given that I have no classpath variable set, it is defaulting to a classpath of current directory. And given the package names, the classpath should be c:\abcd
. And if I set it to that then it compiles blah.java
individually.
C:\abcd\efgh>javac -cp c:\abcd Blah.java
But that still doesn't explain why comb.java compiles fine with no switches:
C:\abcd\efgh>javac comb.java
C:\abcd\efgh>
I understand the package statement in comb.java
applies to the Blah
class and the Greeter
class. I don't see why when compiling comb.java
I don't need to set the classpath specially, whereas I do when compiling javac Blah.java
.
You're compiling without specifying a output "root" for the compiler to build up a package hierarchy from - so it just puts the class files in the same directory as the source files. Then it tries to find the classes later on, but it can't find classes in the efgh
package, because you're already in the efgh
directory and you haven't set your classpath correctly.
Options:
Compile from the source root:
c:\abcd> javac efgh\Greeter.java
c:\abcd> javac efgh\Blah.java
Compile specifying an output root, and putting that on the classpath the second time:
c:\abcd> javac -d ..\bin Greeter.java
c:\abcd> javac -d ..\bin -cp ..\bin Blah.java
Both!
c:\abcd> javac -d bin efhj\Greeter.java
c:\abcd> javac -d bin -cp bin efgh\Blah.java
As for which comb.java
compiles - it doesn't have any dependencies on other classes, so the compiler doesn't need to try to find efgh.Greeter
or efgh.Blah
. It's only failing for Blah
because it's failing to find efgh.Greeter
.
See more on this question at Stackoverflow