Effective Java notes (25) limit the source file to a single top-level class

        Although the Java compiler allows multiple top-level classes to be defined in a single source file, doing so offers no benefit and only entails enormous risks. Because multiple top-level classes are defined in one source file, it is possible to provide multiple definitions for a class. Which definition is used depends on the order in which the source files are passed to the compiler.

        To be more specific, here's an example where the source file contains only one Main class, which references members of two other top-level classes ( Utensil and Dessert ):

public class Main {
    public static void main(String[] args) {
        System.out.println(Utensil.NAME + Dessert.NAME);
    }
}

        Now suppose you define both Utensil and Dessert in a source file called Utensil.java:

class Utensil {
    static final String NAME = " pan";
}
class Dessert {
    static final String NAME = "cake";
}

Of course, the main program prints "pancake".

Now suppose you accidentally define the same two classes in another source file called Dessert.java:

class Utensil {
    static final String NAME = "pot" ;
}
class Dessert {
    static final String NAME = "pie";
}

        If you are lucky enough to use the command javac Main.java Dessert.java to compile the program, then the compilation will fail, and the compiler will remind you that multiple Utensil and Dessert classes are defined. This is because the compiler compiles Main.java first, and when it sees a reference to Utensil (before the reference to Dessert), it looks for this class in Utensil.java, and finds the two classes Utensil and Dessert. When the compiler encounters Dessert.java on the command line, it looks for that file as well, and it encounters the definitions Utensil and Dessert.

        If you use the command javac Main.java or javac Main.java Utensil.java to compile the program, the result will be as if you have not written the Dessert.java file, output pancake. But if the program is compiled with the command javac Dessert.java Main java, potpie will be output. It is clearly unacceptable that the behavior of the program is affected by the order in which the source files are passed to the compiler.

        The fix for this problem is as simple as putting the top-level classes (Utensil and Dessert in this case) into separate source files. If you must put multiple top-level classes into one source file, consider using static member classes instead of separating the two classes into separate source files. If these classes are subject to another class, it is usually better to make them static member classes, because this enhances the readability of the code, and if these classes are declared private, they are less likely to be read. . The following is an example of making a static member class:

public class Test {
    public static void main(String[] args) {
        System.out.println(Utensil.NAME + Dessert . NAME);
    }
    private static class Utensil {
        static final String NAME = "pan";
    }
    private static class Dessert {
        static final String NAME = "cake";
    }
}

        The conclusion is obvious: never put multiple top-level classes or interfaces in one source file . Following this rule ensures that a class does not have multiple definitions at compile time. This in turn ensures that the class files produced by compilation, and the resulting behavior of the program, are not affected by the order in which the source files are passed to the compiler.

Guess you like

Origin blog.csdn.net/java_faep/article/details/132096308