有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javac,当多个应用程序之间存在依赖关系时。java文件,我们需要按某种顺序编译它们吗?

在编译多个文件时。java文件之间有一些依赖关系,我们需要按一定顺序编译它们吗

必须是依赖项。类文件?或者依赖关系可以是一个。java文件

具体来说,当A.java依赖于从B.java文件编译的B.class文件,但B.class尚未创建(即B.java文件尚未编译为B.class)时,我们可以通过在java -cp中指定B.java的目录来编译A.java吗?或者我们需要先将B.java编译成B.class,然后在编译A.java时在java -cp中指定B.class的目录吗

例如,从https://dzone.com/articles/java-8-how-to-create-executable-fatjar-without-ide./src/main/java/com/exec/one/Main.java依赖于./src/main/java/com/exec/one/service/MagicService.java,两者都还没有编译

为什么以下编译失败

$ javac  ./src/main/java/com/exec/one/*.java -d ./out/
./src/main/java/com/exec/one/Main.java:3: error: package com.exec.one.service does not exist
import com.exec.one.service.MagicService;
                           ^
./src/main/java/com/exec/one/Main.java:8: error: cannot find symbol
        MagicService service = new MagicService();
        ^
  symbol:   class MagicService
  location: class Main
./src/main/java/com/exec/one/Main.java:8: error: cannot find symbol
        MagicService service = new MagicService();
                                   ^
  symbol:   class MagicService
  location: class Main
3 errors

为什么下面的编译成功了?如何在一个javac命令中编译它们?在编译中-cp ./src/main/java是如何使用的?编译过程中会发生什么

$ javac -cp ./src/main/java ./src/main/java/com/exec/one/*.java ./src/main/java/com/exec/one/**/*.java

/src/main/java/com/exec/one/main。爪哇

package com.exec.one;                                                                                                                                                                  

import com.exec.one.service.MagicService;                                                                                                                                              

public class Main {                                                                                                                                                                    

    public static void main(String[] args){                                                                                                                                            

        System.out.println("Main Class Start");                                                                                                                                        

        MagicService service = new MagicService();                                                                                                                                     

        System.out.println("MESSAGE : " + service.getMessage());                                                                                                                       

     }                                                                                                                                                                                  

}

/src/main/java/com/exec/one/service/MagicService。爪哇

package com.exec.one.service;                                                                                                                                                          

public class MagicService {                                                                                                                                                            

  private final String message;                                                                                                                                                      

    public MagicService(){                                                                                                                                                             

        this.message = "Magic Message";                                                                                                                                                

    }                                                                                                                                                                                  

    public String getMessage(){                                                                                                                                                        

         return message;                                                                                                                                                                

    }                                                                                                                                                                                  

}

共 (3) 个答案

  1. # 1 楼答案

    看起来应该从路径“/src/main/java”开始。只有在下面,您才有与文件夹名称匹配的包(com.exec.one)。所以做一个“cd src/main/java”并尝试:

    javac ./com/exec/one/*.java
    
  2. # 2 楼答案

    TL;DR如下所述,如果使用这个更简单的命令进行编译,只要求编译Main类,编译器仍然会找到并编译所需的MagicService类,因为它可以在类路径上找到源文件

    javac -cp ./src/main/java ./src/main/java/com/exec/one/Main.java
    

    请参阅编译器文档页面的"Searching for Types" section

    为了方便起见,我在这里引用了所有内容,并添加了亮点(粗体和/或斜体):

    To compile a source file, the compiler often needs information about a type, but the type definition is not in the source files specified on the command line. The compiler needs type information for every class or interface used, extended, or implemented in the source file. This includes classes and interfaces not explicitly mentioned in the source file, but that provide information through inheritance.

    For example, when you create a subclass java.applet.Applet, you are also using the ancestor classes of Applet: java.awt.Panel, java.awt.Container, java.awt.Component, and java.lang.Object.

    When the compiler needs type information, it searches for a source file or class file that defines the type. The compiler searches for class files first in the bootstrap and extension classes, then in the user class path (which by default is the current directory). The user class path is defined by setting the CLASSPATH environment variable or by using the -classpath option.

    If you set the -sourcepath option, then the compiler searches the indicated path for source files. Otherwise, the compiler searches the user class path for both class files and source files.

    You can specify different bootstrap or extension classes with the -bootclasspath and the -extdirs options. See Cross-Compilation Options.

    A successful type search may produce a class file, a source file, or both. If both are found, then you can use the -Xprefer option to instruct the compiler which to use. If newer is specified, then the compiler uses the newer of the two files. If source is specified, the compiler uses the source file. The default is newer.

    If a type search finds a source file for a required type, either by itself, or as a result of the setting for the -Xprefer option, then the compiler reads the source file to get the information it needs. By default the compiler also compiles the source file. You can use the -implicit option to specify the behavior. If none is specified, then no class files are generated for the source file. If class is specified, then class files are generated for the source file.

    The compiler might not discover the need for some type information until after annotation processing completes. When the type information is found in a source file and no -implicit option is specified, the compiler gives a warning that the file is being compiled without being subject to annotation processing. To disable the warning, either specify the file on the command line (so that it will be subject to annotation processing) or use the -implicit option to specify whether or not class files should be generated for such source files.

  3. # 3 楼答案

    Why does the following compilation fail?

    $ javac ./src/main/java/com/exec/one/*.java -d ./out/
    

    因为Main.java(在该命令中拾取的唯一文件)使用了名为com.exec.one.service.MagicService的类,该类在类路径上不可用,也不是正在编译的文件之一

    Why does the following compilation succeed?

    $ javac -cp ./src/main/java ./src/main/java/com/exec/one/*.java ./src/main/java/com/exec/one/**/*.java
    

    因为Main.java使用了名为com.exec.one.service.MagicService的类,该类也是正在编译的文件之一

    How can one compile them in one javac command?

    你已经有了一个命令。程序接受要编译的源文件列表

    Usage: javac <options> <source files>
    

    How is -cp ./src/main/java used in the compilation?

    它用于设置类路径,也就是说,它包括编译过程中可能需要的类文件。在你的例子中,它是无用的

    但是,如果您单独编译了MagicService,并将-cp指向相应的MagicServe.class文件所在的位置(考虑到与其包含的包相匹配的目录结构),它会很有用。这就是Java项目中包含第三方库的方式


    Java编译器不强制进行排序。简单地说,在编译时,所有必需的类都必须可用,可以通过正在编译的源文件,也可以通过类路径中可用的类