从命令行进行Java编译

问题描述 投票:2回答:3

我是一位经验丰富的程序员,但多年来没有使用Java-大多数是C#-并且过去使用过IDE。我正在尝试从Mac上的命令行编译一些代码,但无法获取测试文件来查找源代码。我假设问题出在软件包,文件结构,类路径和导入语句的空间中-但是我投入了几个小时(包括在Stack Overflow上进行搜索),仍然卡住了。

这是我所拥有的:

Directory structure:
ProjectName
|
 --src
    |
     --SourceClass
 --test
    |
     --SourceClassTest
 --external
    |
     --testng-6.8.7.jar

我的SourceClass看起来像这样:

package ProjectName;

public class SourceClass<T>{

}

非常简单。显然,还会有更多-但我想先确保在实际编写代码之前正确设置所有这些设置。

我的测试类如下:

package ProjectName;

import java.util.*;
import org.testng.Assert;
import org.testng.annotations.*;


    public class SourceClassTest{

            @Test
            private void createEmptySourceClass(){
                    SourceClass<Object> sourceClass = new SourceClass<Object>();
                    Assert.assertTrue(sourceClass.isEmtpy());
            }

    }

sourceClass的编译没有问题,“ javac src / *。java”从“ ProjectName”目录运行。我想看到此失败,并伴随“ SourceClass没有isEmpty()方法”的错误,但是我从“ ProjectName”目录运行了这样的javac:

javac test/*.java -classpath external/testng-6.8.7.jar

并获得此异常:

test/SourceClassTest.java:12: error: cannot find symbol
        SourceClass<Object> tree = new SourceClass<Object>();
        ^
  symbol:   class SourceClass
  location: class SourceClassTest
test/SourceClassTest.java:12: error: cannot find symbol
        SourceClass<Object> sourceClass = new SourceClass<Object>();
                                       ^
  symbol:   class SourceClass
  location: class SourceClassTest
2 errors

我已经尝试了很多事情-添加import语句,将源路径添加到javac命令,将sourceClass组合为jar并将其放在bin目录中,然后将其添加到类路径中,但是我无法获得测试以查找SourceClass符号。

知道我在这里缺少什么吗?

java javac importerror
3个回答
3
投票

如果编译到一个单独的目标目录中,它将起作用。例如,

mkdir target
javac -d target/ src/*.java
javac -classpath target/ test/*.java

当您执行javac src/*.java时,它将在.class目录本身中创建src文件。默认情况下,假定您引用的任何类都在同一包中。因此,即使将src/添加到类路径中,它也会查找src/ProjectName/SourceClass.class,但找不到。当您传递-d target/选项时,它将创建正确的包层次结构,从而找到该类。

javac official doc中的相关文档:

您应将源文件排列在目录树中,以反映他们的包裹树。例如,如果您将所有源文件保留在C:\ workspace,com.mysoft.mypack.MyClass的源代码应为在C:\ workspace \ com \ mysoft \ mypack \ MyClass.java中。

默认情况下,编译器将每个类文件放在与它的源文件。您可以使用以下命令指定一个单独的目标目录-d(请参阅下面的选项)。

...

...

-d 目录设置类文件的目标目录。该目录必须已经存在; javac不会创建它。如果一个班级是包的一部分,javac将类文件放在子目录中反映软件包名称,并根据需要创建目录。对于例如,如果您指定-d C:\ myclasses并且该类被调用com.mypackage.MyClass,则该类文件被称为C:\ myclasses \ com \ mypackage \ MyClass.class。如果未指定-d,javac将每个类文件与源文件放在同一目录中从中生成它。

注意:-d指定的目录不会自动添加到您的用户类路径。


1
投票

我猜是找不到SourceClass,因为定义该类的文件在src下,并且您没有在javac命令行中提及该目录。

如果我是你,我将文件层次结构更改为此:

ProjectName/src/ProjectName/SourceClass.java
ProjectName/src/ProjectName/SourceClassTest.java
ProjectName/external/testng-6.8.7.jar

然后运行javac src/ProjectName/*.java -classpath external/testng-6.8.7.jar

或保持文件层次结构不变,然后运行javac src/*.java test/*.java -classpath external/testng-6.8.7.jar


0
投票

接受的答案是正确的,但是它遗漏了一个关键点:当要求javac编译*.java(而不是foo.java,然后是foo2.java ...)时,它将它们视为单个包并接受它们之间的引用。

这就是魔术。其他语言对头文件的隐式处理较少。

即使在阅读了这篇文章之后,我花了一些时间才弄清楚,与我固有的假设相反,一个程序在文件上一个接一个地运行将产生(应该)产生与在一组文件上运行该程序相同的结果。 。我的错; *不仅是方便,而且很重要。

© www.soinside.com 2019 - 2024. All rights reserved.