简体   繁体   中英

java compiling from the command line

I am an experienced programmer, but haven't used Java in years - mostly C# - and used an IDE in the past. I'm trying to compile some code from the command line on my Mac, but can't get my test file to find my source code. I'm assuming the problem lies somewhere in the space of packages, file structure, classpaths, and import statements - but I've put a couple hours in (including hunting on Stack Overflow) and am still stuck.

Here's what I have:

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

My SourceClass looks like this:

package ProjectName;

public class SourceClass<T>{

}

Very simple. Obviously, there will be more - but I wanted to start with making sure I had all this setup stuff correct before I actually did coding.

My test class looks like this:

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());
            }

    }

The sourceClass compiles with no issue with "javac src/*.java", run from the "ProjectName" directory. I want to see this fail with an error along the lines of "SourceClass doesn't have an isEmpty() method", but instead I run javac like this from the "ProjectName" directory:

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

and get this exception:

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

I've tried a lot of things -adding an import statement, adding a sourcepath to the javac command, compiing the sourceClass as a jar and putting it in the bin directory then adding that to the classpath, but I can't get the test to find the SourceClass symbols.

Any idea what I am missing here?

It works if you compile into a separate target directory. Eg,

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

When you do javac src/*.java , it will create the .class file in the src directory itself. By default, any classes you reference are assumed to be in the same package. So even if you add src/ to the classpath, it looks for src/ProjectName/SourceClass.class , which it does not find. When you pass the -d target/ option, it creates the proper package hierarchy, so and finds the class.

Relevant documentation from the javac official doc :

You should arrange source files in a directory tree that reflects their package tree. For example, if you keep all your source files in C:\\workspace, the source code for com.mysoft.mypack.MyClass should be in C:\\workspace\\com\\mysoft\\mypack\\MyClass.java.

By default, the compiler puts each class file in the same directory as its source file. You can specify a separate destination directory with -d (see Options, below).

...

...

-d directory Set the destination directory for class files. The directory must already exist; javac will not create it. If a class is part of a package, javac puts the class file in a subdirectory reflecting the package name, creating directories as needed. For example, if you specify -d C:\\myclasses and the class is called com.mypackage.MyClass, then the class file is called C:\\myclasses\\com\\mypackage\\MyClass.class. If -d is not specified, javac puts each class files in the same directory as the source file from which it was generated.

Note: The directory specified by -d is not automatically added to your user class path.

My guess is it can't find SourceClass because the file defining that class is under src , and you didn't mention that directory in your javac command line.

If I were you, I would change the file hierarchy to this:

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

Then run javac src/ProjectName/*.java -classpath external/testng-6.8.7.jar .

Or keep the file hierarchy the way it is, and run javac src/*.java test/*.java -classpath external/testng-6.8.7.jar

The accepted answer is correct, but it misses one critical point: when javac is asked to compile *.java (as opposed to foo.java , and then foo2.java ...) it treats them as a single package and accepts references between them.

That's the magic. Other languages do this less implicitly with header files.

Even after reading this post, it took me some time to figure that out, against my inherent assumption that a program running singly on files one after the other would (should) produce the same result as running that program on a group of files. My bad; the * is NOT a mere convenience, but critical.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM