【问题标题】:Why do these classes only compile when in the same file?为什么这些类只在同一个文件中编译?
【发布时间】:2014-08-02 18:15:04
【问题描述】:

我有这个目录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&gt;type Blah.java

package efgh;

class Blah {

    Greeter greeter = new Greeter();

    public static void main(String[] args) {}

}

C:\abcd\efgh&gt;type Greeter.java

package efgh;

class Greeter {

    public static void main(String[] args) {}

}    

C:\abcd\efgh&gt;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&gt;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

我知道从技术上讲,我的类路径设置不正确。因为,鉴于我没有设置类路径变量,它默认为当前目录的类路径。给定包名,类路径应该是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 时需要。

【问题讨论】:

标签: java classpath javac


【解决方案1】:

您已经进行了所有分析,最后一点很简单:comb.java 不需要任何类路径,因为它是完全独立的:Greeter 引用自 @987654323 @ 是否在同一个文件中。

一般情况下,javac 在编译类 A 时需要查阅类路径,该类 A 引用了一个 B 类,而 B 类不在传递给它的文件列表中。

例如,试试javac Blah.java Greeter.java,它应该也可以工作。

【讨论】:

    【解决方案2】:

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

    选项:

    • 从源码根目录编译:

      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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 2018-01-05
      • 2020-08-30
      • 2014-12-09
      • 1970-01-01
      相关资源
      最近更新 更多