javaintellij-ideapackagejavacclassnotfoundexception

Why can't my class be run after declaring package and be found by another class in the same package/folder?


I am having problems understanding how packages work. Not using any IDE.

I have the following folder structure: ~/dropbox/api/data

Inside the data folder, there are (only) Producer.java, Consumer.java.

api
├── data
     ├── Consumer.java
     ├── Producer.java
     └── Producer.class
package data;

public class Producer {
   
   public static void main(String[] args) {
      //do some production
   }

   public static Producer getProducer() {
      //call constructor and return instance
   }
}
----------------
package data;

public class Consumer {

   public static void main(String[] args) {
      Producer worker = getProducer();
   }

}

I cd to data folder and javac Producer.java to compile Producer.class in the same folder. Then when I run java Producer, I get Error: Could not find or load main class Producer Caused by: java.lang.NoClassDefFoundError: Producer (wrong name: data/Producer).

Same error, when I tried java Producer and java data.Producer from the parent api folder, and java data.Producer in data folder. Screenshot

  1. What's wrong here? If I remove the package data;, it compiles (javac) and runs (java) fine in data folder.

Also, when I tried javac Consumer.java, I get error: cannot find symbol Producer. They are in the same folder and declared same package.

  1. What's wrong here?

Solution

  • The java command requires that you specify the fully qualified name of the class. So, java Producer will never work; you must type java data.Producer.

    But that's not all.

    Package follows dir. So, when you type java data.Producer as you must, java tries to load data/Producer.class from each entry on the classpath. By default, the current dir is on the classpath, but if you've been messing with e.g. the CLASSPATH environment variable it might not be. To make sure that's not the problem, java -cp . data.Producer.

    Same error, when I tried java Producer and java data.Producer from the parent api folder,

    No, you messed up there somehow. java data.Producer from the api folder will work. Just to be sure, try java -cp . data.Producer (and if that does work, unmessup whatever you messed up with the CLASSPATH variable. Or just get used to doing that, it's not a bad idea).

    Also, when I tried javac Consumer.java, I get error: cannot find symbol Producer.

    Same problem, you need to run javac data/Consumer.java from the api dir.

    There's a reason you don't use javac directly and instead use a build tool or IDE.