java compile and execution

Let’s compile a simple java program in current directory(javac Test.java):

//Test.java
class Test
{
  String a="hello";
  public static void main(String[]args)
  {
    Test b=new Test();
    b.a="world";
    System.out.println(b.a);
    App app=new App();
    app.fun();
  }
}

When java compiler finds a new class “App”, it will try to find a java source file called “App.java”(case sensitive) in current directory. If it can’t find the source file, the compiler will print an error:”cannot find symbol”. If there is a source file “App.java” in current folder but that file does not contain the class “App”, the compiler will print the error “Error source file App.java, the file does not contain class App. Please delete this file or guarantee the file is in correct source sub-folders”. If App.java contains the class App but App is in another package such as fruit(i.e., there is a package statement at the beginning of App.java), the error persists, because the compiler is seeking the App class that is in the “unnamed package”.

If we let both the Test class and the App class in the same fruit package as follows:

//Test.java
package fruit;

class Test
{
  String a="hello";
  public static void main(String[]args)
  {
    Test b=new Test();
    b.a="world";
    System.out.println(b.a);
    App app=new App();
    app.fun();
  }
}

 

//App.java
package fruit;

class App
{
  String a="aaa";
  void fun()
  {
    System.out.println("App");
  }
}

The compiler still complains “cannot find the symbol App”.  Why? It is because the compiler is now seeking the source file “fruit/App.java” rather than “./App.java”. If you move “App.java” from current folder to a sub-folder “fruit”, the compile command “java Test.java” has no problem. Note that the compiler seeks the source file only when it can not find App.class in fruit sub-folder. So you can compile App.java to App.class in current directory and move the generated App.class to “fruit/”, then compile Test.java in current directory.

Now let’s run the class Test “java Test”. It prints the error ” cannot find or load the main class Test” despite the fact that Test.class is right in current directory.  In fact, java loads the Test.class but find the class “Test” is actually in package fruit, not in the “unnamed package” as you specified.  If you run “java fruit.Test”, it complains the same error. Why? This is because as you specified in the command line, java will find the class in fruit sub-folder instead of current folder. If you move Test.class to the sub-directory “fruit/”, the program will be executed without problem.

Now let’s simulate the cross-package access scenario. We make the Test class be in the unnamed package and the App in the fruit package. Both Test.java and App.java are in current directory. We import the fruit package in Test.java:

//Test.java
import fruit.App;

class Test
{
  String a="hello";
  public static void main(String[]args)
  {
    Test b=new Test();
    b.a="world";
    System.out.println(b.a);
    App app=new App();
    app.fun();
  }
}

Now compiling Test.java would produce two errors: package fruit does not exist, and .\App.java does not contain class App. To resolve the first problem, we compile the App.class first and move the generated App.class to “fruit/” sub-folder. Now the first error that’s related to import changes to “App in fruit is not public, cannot access it from outside of the package”. Let’s change the App class to public in App.java and re-compile App.java. The first error now changes to ” fun() in App is not public and can not be accessed from outside of the package”. The second error disappears. After adding the “public” modifier to the declaration of fun() in App, all errors disappear and Test can be executed successfully.

//App.java
package fruit;

public class App
{
  String a="aaa";
  public void fun()
  {
    System.out.println("App");
  }
}

Now we know that when importing a class in a package, javac will check if the class is public and refuse to import it if not. Even the class is set to public and can be imported, javac still does not allow to call functions of that class which are not declared as public. There is no such concept of “public class” in C++ as C++ does not have the concept of package. Public class in java serves solely for the concept of package. A java class can only be declared with the “public” modifier or without a modifier. “private” and “protected” modifier can not be applied to a java class.  You can define multiple classes in one source file but only one class can be declared as public because the file name should be consistent with the name of the public class and there is only one file name per file.(If there is no public class defined in a file, the file can have any file name.)

 

Comments are closed, but trackbacks and pingbacks are open.