javac和java的路径问题 设定项目目录为packageTest,举三个例子来讨论javac和java两个命令对路径的要求。 例1: javac的搜索根目录为当前目录,例如,在test下建立如下目录:aaa/bbb/ccc,再在test下建立一个文件:Main.java,内容如下: view plaincopy to clipboardprint? 1. package aaa.bbb.ccc; 2. import java.io.*; 3. 4. public class Main { 5. public static void main (String[] args) throws IOException { 6. System.out.println("I am class Main."); 7. b.say(); 8. } 9. static B b = new B (); 10. } 11. 12. class B { 13. public void say () 14. { 15. System.out.println("I am class B."); 16. } 17. } 在packageTest目录下编译: $ javac Main.java 仍在packageTest目录下运行: $ java Main 失败。因为Main类在包aaa.bbb.ccc中,java会在CLASSPATH(假设已经将当前目录:./加入到了CLASSPATH中)下找aaa/bbb/ccc/Main.class,当然找不到。实际上,即使把CLASSPATH设为./aaa/bbb/ccc,java仍然找不到Main,这里涉及到一个fully-qualified class name的概念,即,当给一个类打了包,类的名字就不再是原来的名字,必须加上包的名字,在本例子中,Main类被打在aaa/bbb/ccc包中后,其fully-qualified class name为aaa.bbb.ccc.Main。当然,这和将类打在默认包中时的情况不同,类打在默认包中时没有fully-qualified class name,也可以说其fully-qualified class name就是原生的类名。好了,再运行: $ java aaa.bbb.ccc.Main 仍失败!错误提示说没有找到 main class,哦,对,原来是没把Main拷到aaa/bbb/ccc中去,拷进去后再运行: $ java aaa.bbb.ccc.Main 仍失败!!错误提示说没有找到 main class,不知道为什么还会提示这个错误,其实错误原因是B.class放的位置不对由于class B和Main放在同一个翻译单元中,故编译器图方便直接把B.class放在了当前目录中,实际上class B也是aaa.bbb.ccc包中的成员,所以运行时java没有在这个包中找到class B,当把B.class拷到aaa/bbb/ccc目录下后再运行: $ java aaa.bbb.ccc.Main 成功显示结果: I am class Main. I am class B. 例2: 对Main.java做修改,把要使用的类B移出当前翻译单元: view plaincopy to clipboardprint? 1. package aaa.bbb.ccc; 2. import java.io.*; 3. 4. public class Main { 5. public static void main (String[] args) throws IOException { 6. System.out.println("I am class Main."); 7. b.say(); 8. } 9. static B b = new B (); 10. } 然后在packageTest下新建一个B.java: view plaincopy to clipboardprint? 1. package aaa.bbb.ccc; 2. import java.io.*; 3. public class B { 4. void say () { 5. System.out.println("I am the goddamn B!"); 6. } 7. } 编译: $ javac Main.java 失败。原因是javac没有找到symbol: class B,把B.java拷到aaa/bbb/ccc下后,编译成功,并在aaa/bbb/ccc下生成了B.class。原来javac在本翻译单元中找不到B后会去包aaa.bbb.ccc中找,所以package语句不止跟java有关,javac也要用它。实际上,javac需要的也是class文件,即javac发现import语句后,也要去CLASSPATH中去找编译时所需要的类,如果class文件存在,直接使用;如果不存在,对应的java源文件存在也行,这时,javac会先将B.java编译成B.class,这样Main中所需要的aaa.bbb.ccc.B就存在了,编译通过。因此,不论是java还是javac还是其它程序,只要其找的是class文件,就需要到CLASSPATH指定的目录中去找。如果CLASSPATH不设,默认为当前目录".",故即使echo出的$CLASSPATH什么也没有,它也是".",这一点比较奇怪。另外,目前还不清楚java的“库“放在哪,比如上面程序中的java.io.*,而且java怎么去找这些class,至少应该不是通过CLASSPATH。javac编译过程中寻找类名的顺序是定死的,这个顺序参见附记。 接下来在test中运行: $ java aaa.bbb.ccc.Main 失败。忘记把Main.class拷到aaa/bbb/ccc中去了。拷过去以后在test中执行上面命令,结果为: I am class Main. I am the goddamn B! 例3: 主要想明确一下javac搜索类型的顺序。 Main.java如例1: view plaincopy to clipboardprint? 1. package aaa.bbb.ccc; 2. import java.io.*; 3. 4. public class Main { 5. public static void main (String[] args) throws IOException { 6. System.out.println("I am class Main."); 7. b.say(); 8. } 9. static B b = new B (); 10. } 11. 12. class B { 13. public void say () 14. { 15. System.out.println("I am class B."); 16. } 17. } 另外还有B.java: view plaincopy to clipboardprint? 1. package aaa.bbb.ccc; 2. import java.io.*; 3. public class B { 4. void say () { 5. System.out.println("I am the goddamn B!"); 6. } 7. } 这次两个class都放在aaa/bbb/ccc下,在packageTest中执行命令: $ javac aaa/bbb/ccc/Main.java 在aaa/bbb/ccc下生成Main.class和B.class,然后运行: $ java aaa.bbb.ccc.Main 结果为: I am class Main. I am class B. 可见生成的B.class由Main.java中的class B生成,这体现了javac的一种搜索类型的顺序。 javac参数(-classpath, -sourcepath)详解 首先是官方说法: -classpath: 设置用户类路径,它将覆盖 CLASSPATH 环境变量中的用户类路径。若既未指定 CLASSPATH 又未指定 -classpath,则用户类路径由当前目录构成。 -sourcepath: sourcepath用来查找源文件的,具体来说就是,在我们编译A时,如果A依赖B,而B在classpath中又找不到,这时就要在sourcepath中查找B的源文件。指定用以查找类或接口定义的源代码路径。与用户类路径一样,源路径项用分号 (;) 进行分隔,它们可以是目录、JAR 归档文件或 ZIP 归档文件。如果使用包,那么目录或归档文件中的本地路径名必须反映包名。 注意:通过类路径查找的类,如果找到了其源文件,则可能会自动被重新编译。 官方说法很简洁,但是具体操作起来总觉得不太清晰,我们还是找几个例子,来具体分析一下: 具体例子: 假设我们有如下的目录结构: src-| |-foo-| |-Testfoo.java |-baz-| |-Testbaz.java classes-| 其中Testfoo.java: package foo; public class Testfoo { //.... } 其中Testbaz.java: package baz; import foo.Testfoo; public class Testbaz { //... } 也就是说Testbaz对Testfoo有引用。 我们目标是把Testbaz编译到目录classes里面,试用如下的命令: javac -d classes src/baz/Testbaz.java 命令失败,因为找不到它依赖的Testfoo。我们可以用以下三种方式来实现: 1.我们最容易考虑到的就是编译被依赖的Testfoo类,并将其加入Testbaz的CLASSPATH javac -d classes src/foo/Testfoo.java javac -d classes -classpath classes src/baz/Testbaz.java 第二行使用了-classpath,使得编译器在寻找Testfoo类的时候以classes为根目录,根据根目录和package名,类名最终定位了需要用的(已编译出来的)Testfoo类。 2.在编译Testbaz的时候把被依赖的Testfoo类加入SOURCEPATH javac -d classes -sourcepath src src/baz/Testbaz.java 在编译条件里面加入-verbose可以很清楚的看到,编译器在寻找Testfoo类的时候,以src为根目录,根据根目录和package名,类名最终定位了需要用的(源代码)Testfoo类。 3.把CLASSPATH和SOURCEPATH两者都加进来 javac -d classes src/foo/Testfoo.java javac -d classes -sourcepath src -classpath classes src/baz/Testbaz.java 两个属性都被加入,编译器首先会判断Testfoo.class和Testfoo.java是否同时存在。如果单独存在,则适应于以上的方法之一。如果同时存在,则判断.class是否是.java的最新编译,如果有差异,则重新编译.java来覆盖.class 有必要补充一下-d参数: -d参数是很好的把源程序和目标代码分离的参数。-d制定的是目标代码的根目录,源文件的包的结构将以目录形式反映到根目录上。美中不足的是-d需要指定已经存在的目录,不能自动创建。 再来一例子 文件结构如下,其中A.java头部引用B和C files.txt为sourcepath列表,注意路径以分号分隔且在同一行(不知为什么,可能与classpath规范类似,路径以分号分隔吧),不能以回车或者空格分隔,另外路径指类全名(含包名)所在的目录,如A .java中import c.C;指c.C所在的目录即E:\test\src,而不是C.java的路径即E:\test\src\c。 javas.txt包含多个要编译的java源文件,以空格或者回车分隔,分号不行。也可以将多个文件写在javac命令行中,文件名以空格分隔。要编译的源文件要写成含”\”符号的完整路径,不能写成含”.”符号的包形式,这与java命令不同,如javac E:\test\b\B.java与java b.B。 E:\test\a\A.java E:\test\b\B.java E:\test\src\c\C.java
相关推荐
Java 和 javac 命令是 Java 语言的基本组成部分,它们在 Java 应用程序的编译和执行过程中扮演着重要的角色。javac 命令用于编译 Java 程序源代码,生成字节码文件,而 java 命令用于执行已经编译的字节码文件。 ...
《在EditPlus中配置javac和java命令》 在IT行业中,编辑器是开发者的重要工具,而EditPlus作为一款功能强大的文本编辑器,因其简洁的界面、高效的代码编写功能以及丰富的自定义设置,深受广大程序员的喜爱。然而,...
在这个窗口中,我们需要创建两个新的工具组,分别对应javac(Java编译器)和java(Java解释器)。 1. 创建javac命令: - 在“组名称”下,新建一个组,命名为“Java编译运行”。 - 点击“添加工具”,选择“应用...
在Windows命令行中使用Java和相关命令如javac(Java编译器)和javap(Java类文件反编译器)是Java开发者的基本技能。为了深入理解这些命令的使用方法,让我们逐步详细地讨论每一个命令的具体用法和相关知识点。 ...
通过阅读和分析javac的源代码,你可以了解到Java编译器如何处理语法错误、类型检查、优化和生成字节码等核心功能。这对于提升Java编程技能、理解编译原理和开发自定义编译器或编译插件都十分有帮助。 **标签相关...
在深入探讨“java能执行,javac不能执行”的原因之前,我们先来了解下Java环境配置的基本原理。...通过以上步骤,通常可以有效解决“java能执行,javac不能执行”的问题,确保Java开发环境的完整性和稳定性。
- 类似于JAVA_HOME和PATH的设置,可以在系统变量中添加CLASSPATH,用于指定编译和运行时的类库路径。 - 变量值可以包含多个路径,路径之间用分号分隔。 2. **使用环境变量管理工具** - 对于复杂的环境配置,可以...
Java路径配置对于Windows 7用户来说是至关重要的步骤,尤其是对于初学者而言,因为这是运行和开发Java程序的基础。本文将详细解释如何正确配置Java环境变量,以确保系统能够识别并执行Java命令。 首先,我们需要...
总结一下,DOS环境下使用`javac`编译和`java`执行多个包下的`.java`文件涉及理解Java项目的目录结构,正确设置类路径,以及熟练使用DOS命令行。在实际开发中,你可能还需要结合构建工具如Maven或Gradle自动化这些...
在Java开发中,实时的语法检查(也称为linter)对于提高代码质量和减少错误至关重要,而Atom-linter-javac就是这样一款工具,它集成Javac编译器,能够在你保存Java源文件时自动检查代码的语法错误。 首先,我们需要...
本文将详细介绍如何配置EditPlus,使其支持直接运行`javac`和`java`命令,从而在编辑器内部完成Java程序的编译和运行,免去频繁切换到命令行窗口的繁琐步骤。 首先,打开EditPlus,选择菜单栏中的“工具”->“配置...
在 Java 开发中,经常会遇到一个问题,即 javac 编译成功后,用 java 运行 Class 文件却出现“找不到或无法加载主类”的错误信息。这种问题看似很复杂,但实际上解决起来非常简单。下面我们将详细讲解该问题的解决...
Java路径设置对于软件开发至关重要,因为它确保了操作系统能够正确地找到并执行Java相关的程序和类。以下是关于JAVA_HOME、PATH和CLASSPATH这三个关键环境变量的详细说明。 **JAVA_HOME** JAVA_HOME环境变量指示的...
javac 在编译过程中会检测语法错误、类型不匹配等问题,并生成错误和警告信息。这些信息通过 `com.sun.tools.javac.main.DiagnosticListener` 接口传递给用户。 5. **注解处理**: Java 提供了注解(Annotation)...
在Java编程中,获取JDK(Java Development Kit)的安装路径是常见的需求,尤其是在系统配置、依赖管理和自动化脚本中。下面将详细讲解如何通过环境变量和正则表达式匹配来实现这一目标。 首先,我们需要了解Java的...
Java的编译路径和运行路径是Java开发过程中两个至关重要的概念。它们决定了程序源代码如何被转换成可执行的字节码以及运行时系统如何找到这些字节码。本文将详细探讨这两个概念。 首先,我们来看Java的编译路径。在...
以上内容概述了Java学习路径中关于工具的选择与使用的关键知识点,希望对Java初学者有所启发和帮助。接下来可以进一步深入学习Java的核心概念和技术,如面向对象编程、集合框架、异常处理等,并通过实践项目来提升...
本文将深入解析“java安装路径设置”的关键知识点,包括JAVA_HOME环境变量的设定、Path环境变量的更新以及如何确保Java环境的正确配置。 ### JAVA_HOME环境变量 #### 定义与作用 JAVA_HOME是一个系统环境变量,...
Java路径设置是每个Java开发者必须掌握的基本技能,尤其是在命令行环境下执行Java程序时。这篇教程将引导初学者了解如何在不同的操作系统中配置Java环境变量,确保系统能够正确找到Java开发工具(JDK)并运行Java...
JDK9作为Java的重要版本,对javac进行了一系列改进和优化,提升了开发效率和程序性能。然而,直接使用从压缩包"jdk9_javac.rar"解压出来的编译器可能会遇到package冲突的问题。本文将深入探讨JDK9中javac编译器的...