Spoiled execution

exercise No. 219

Q:

Consider the following class being defined in Driver.java:

package experiment;

public class Driver {

  public static void main(String[] args) {
    System.out.println("All the best to your exam!");
  }
}

Execution works as expected:

> java experiment.Driver 
All the best to your exam!

We now add a String class String.java to the same package:

package experiment;

public class String {}

Although Driver.java remains completely unchanged execution no longer works:

> java experiment.Driver 
Error: Main method not found in class experiment.Driver, please define the main method as:
   public static void main(String[] args) ...
  1. Explain the different behaviour.

  2. Propose a solution by exclusively modifying Driver.java.

A:

  1. There is nothing wrong here with respect to compilation. However the Java Virtual Machine (JVM) specification requires exactly the following signature for program execution:

    public static void main(java.lang.String[] args)

    This allows for passing command line arguments as standard Java Strings. More precisely by instances of class String from package java.lang. However by adding an own String class to the very same experimental package this class gets precedence over java.lang.String. Driver is now equivalent to:

    package experiment;
    
    public class Driver {
    
      public static void main(experiment.String[] args) {
        System.out.println("All the best to your exam!");
      }
    }

    This signature violates the JVM contract with respect to Java application start. It however does compile flawlessly.

  2. Solving the problem requires explicit package qualification with respect to class java.lang.String. We may choose from either of:

    • package experiment;
      
      public class Driver {
      
        public static void main(java.lang.String[] args) { // Explicit package specification
          System.out.println("All the best to your exam!");
        }
      }
    • package experiment;
      
      import java.lang.String; // Now taking precedence over experimental.string
      
      public class Driver {
      
        public static void main(String[] args) {
          System.out.println("All the best to your exam!");
        }
      }