views:

2589

answers:

6

I'm a C++ developer - not a java developer, but have to get this code working...

I have 2 public classes that will be used by another product. I used the package directive in each of the java files.

package com.company.thing;

class MyClass ...

When I try to compile a test app that uses that I add

import com.company.thing.*;

The javac compiler fails with errors about com.company does not exist. (even if I compile it in the same directory as the class files I just made a package of)

I am sure I am doing something bone-headed and silly.

I've read the http://java.sun.com/docs/books/tutorial/java/package/usepkgs.html pages and tried to set up a directory structure like /com/company/thing etc, but either I have totally screwed it all up or am missing something else.

EDIT thanks for the suggestions - I had tried the classpath previously. It does not help.

I tried compiling

javac -classpath <parent> client.java

and the result is:

package com.company does not exist

I have the code I want to import (the two java files) in \com\company\product. I compile those fine. (they contain MyClass) I even made a jar file for them. I copied the jar file up to the parent directory.

I then did (in the parent directory with the client java file)

javac -cp <jarfile> *.java

the result is:

cannot access MyClass
bad class file: MyClass.class(:MyClass.class)
class file contains wrong class: com.company.product.MyClass
Please remove or make sure it appears in the correct subdirectory of the classpath.

EDIT

I got the client code to compile and run if I used the fully qualified name for MyClass and compiled it in the parent directory. I am totally confused now.

compiled with no classpath set - just

javac *.java

in the parent directory - and it worked fine.

I can get a test app to compile, but that is not going to cut it when i have to integrate it into the production code. Still looking for help.

EDIT:

Finally - not sure why it didn't work before - but I cleaned up all the files all over the directory structure and now it works.

Thanks

+4  A: 

It sounds like you are on the right track with your directory structure. When you compile the dependent code, specify the -classpath argument of javac. Use the parent directory of the com directory, where com, in turn, contains company/thing/YourClass.class

erickson
+1  A: 

check your classpath.

Hank Gay
+3  A: 

Yes, this is a classpath issue. You need to tell the compiler and runtime that the directory where your .class files live is part of the CLASSPATH. The directory that you need to add is the parent of the "com" directory at the start of your package structure.

You do this using the -classpath argument for both javac.exe and java.exe.

Should also ask how the 3rd party classes you're using are packaged. If they're in a JAR, and I'd recommend that you have them in one, you add the .jar file to the classpath:

java -classpath .;company.jar foo.bar.baz.YourClass

Google for "Java classpath". It'll find links like this.

One more thing: "import" isn't loading classes. All it does it save you typing. When you include an import statement, you don't have to use the fully-resolved class name in your code - you can type "Foo" instead of "com.company.thing.Foo". That's all it's doing.

duffymo
+3  A: 

You got a bunch of good answers, so I'll just throw out a suggestion. If you are going to be working on this project for more than 2 days, download eclipse or netbeans and build your project in there.

If you are not normally a java programmer, then the help it will give you will be invaluable.

It's not worth the 1/2 hour download/install if you are only spending 2 hours on it.

Bill K
+1  A: 

The standard Java classloader is a stickler for directory structure. Each entry in the classpath is a directory or jar file (or zip file, really), which it then searches for the given class file. For example, if your classpath is ".;my.jar", it will search for com.example.Foo in the following locations:

./com/example/
my.jar:/com/example/

That is, it will look in the subdirectory that has the 'modified name' of the package, where '.' is replaced with the file separator.

Also, it is noteworthy that you cannot nest .jar files.

krakatoa
+6  A: 

Okay, just to clarify things that have already been posted.

You should have the directory com, containing the directory company, containing the directory example, containing the file MyClass.java.

From the folder containing com, run:

$ javac com\company\example\MyClass.java

Then:

$ java com.company.example.MyClass
Hello from MyClass!

These must both be done from the root of the source tree. Otherwise, javac and java won't be able to find any other packages (in fact, java wouldn't even be able to run MyClass).

A short example

I created the folders "testpackage" and "testpackage2". Inside testpackage, I created TestPackageClass.java containing the following code:

package testpackage;

import testpackage2.MyClass;

public class TestPackageClass {
    public static void main(String[] args) {
        System.out.println("Hello from testpackage.TestPackageClass!");
        System.out.println("Now accessing " + MyClass.NAME);
    }
}

Inside testpackage2, I created MyClass.java containing the following code:

package testpackage2;
public class MyClass {
    public static String NAME = "testpackage2.MyClass";
}

From the directory containing the two new folders, I ran:

C:\examples>javac testpackage\*.java

C:\examples>javac testpackage2\*.java

Then:

C:\examples>java testpackage.TestPackageClass
Hello from testpackage.TestPackageClass!
Now accessing testpackage2.MyClass

Does that make things any clearer?

Michael Myers
Gah, you went and edited the question while I was writing this up!
Michael Myers