为什么这些类只在同一个文件中编译?

时间:2014-08-02 18:15:05

标签: java classpath javac

我有这个目录c:\abcd它没有文件,但有一个子目录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

如您所见,efgh子目录有3个文件。 Blah.javaGreeter.javacomb.java

Blah.java有一个班级,Greeter.java有一个班级。

comb.java恰好包含Blah.javaGreeter.java的代码,因此它有两个类。它是多余的,但它是为了展示一些东西。这是一个梳子编译的情况,而其中一个单独的文件(Blah.java)没有。

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

这些是三个文件的内容

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

所以,comb.java编译。

我看到它生成了Blah.classGreeter.class,这进一步证明了它已编译,但我现在将删除这些.class文件。这就是我的意思,javac comb.java有效。

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

现在我将单独编译它们。并且它不能很好地工作..编译Blah.java会产生错误。

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

我知道技术上,我的类路径设置不正确。因为,由于我没有设置classpath变量,因此它默认为当前目录的类路径。并且给定包名称,类路径应为c:\abcd。如果我将其设置为那么它会单独编译blah.java

C:\abcd\efgh>javac -cp c:\abcd Blah.java

但这仍然无法解释为什么comb.java在没有开关的情况下编译得很好:

C:\abcd\efgh>javac comb.java

C:\abcd\efgh>

我理解comb.java中的包语句适用于Blah类和Greeter类。编译comb.java时我不明白为什么我不需要特别设置类路径,而我在编译javac Blah.java时也这样做。

2 个答案:

答案 0 :(得分:3)

您已经完成了所有分析,最后一点非常简单:comb.java 任何类路径都是因为它完全是自包含的:{{1从Greeter引用的文件存在于同一文件中。

通常,Blah需要在编译类A时查阅类路径,类A引用类B,在传递给它的文件列表中

例如,尝试javac,它也可以正常工作。

答案 1 :(得分:2)

您正在编译而没有为编译器指定输出“root”以构建包层次结构 - 因此它只是将类文件放在与源文件相同的目录中。然后它尝试稍后查找类,但它无法在efgh包中找到类,因为您已经在efgh目录中并且没有正确设置类路径。 / p>

选项:

  • 从源根编译:

    c:\abcd> javac efgh\Greeter.java
    c:\abcd> javac efgh\Blah.java
    
  • 编译指定输出根,并将其第二次放在类路径上:

    c:\abcd> javac -d ..\bin Greeter.java
    c:\abcd> javac -d ..\bin -cp ..\bin Blah.java
    
  • 两个!

    c:\abcd> javac -d bin efhj\Greeter.java
    c:\abcd> javac -d bin -cp bin efgh\Blah.java
    

至于哪个comb.java编译 - 它与其他类没有任何依赖关系,因此编译器不需要尝试查找efgh.Greeterefgh.Blah。它仅在Blah失败,因为它找不到efgh.Greeter