This is just convention. In fact, even the name main(), and the arguments passed in are purely convention.
When you run java.exe (or javaw.exe on Windows), what is really happening is a couple of Java Native Interface (JNI) calls. These calls load the DLL that is really the JVM (that's right - java.exe is NOT the JVM). JNI is the tool that we use when we have to bridge the virtual machine world, and the world of C, C++, etc... The reverse is also true - it is not possible (at least to my knowledge) to actually get a JVM running without using JNI.
Basically, java.exe is a super simple C application that parses the command line, creates a new String array in the JVM to hold those arguments, parses out the class name that you specified as containing main(), uses JNI calls to find the main() method itself, then invokes the main() method, passing in the newly created string array as a parameter. This is very, very much like what you do when you use reflection from Java - it just uses confusingly named native function calls instead.
It would be perfectly legal for you to write your own version of java.exe (the source is distributed with the JDK) and have it do something entirely different. In fact, that's exactly what we do with all of our Java-based apps.
Each of our Java apps has its own launcher. We primarily do this so we get our own icon and process name, but it has come in handy in other situations where we want to do something besides the regular main() call to get things going (For example, in one case we are doing COM interoperability, and we actually pass a COM handle into main() instead of a string array).
So, long and short: the reason it is static is b/c that's convenient. The reason it's called 'main' is that it had to be something, and main() is what they did in the old days of C (and in those days, the name of the function was important). I suppose that java.exe could have allowed you to just specify a fully qualified main method name, instead of just the class (java com.mycompany.Foo.someSpecialMain) - but that just makes it harder on IDEs to auto-detect the 'launchable' classes in a project.
Switch statements with String
cases have been implemented in Java SE 7, at least 16 years after they were first requested. A clear reason for the delay was not provided, but it likely had to do with performance.
Implementation in JDK 7
The feature has now been implemented in javac
with a "de-sugaring" process; a clean, high-level syntax using String
constants in case
declarations is expanded at compile-time into more complex code following a pattern. The resulting code uses JVM instructions that have always existed.
A switch
with String
cases is translated into two switches during compilation. The first maps each string to a unique integer—its position in the original switch. This is done by first switching on the hash code of the label. The corresponding case is an if
statement that tests string equality; if there are collisions on the hash, the test is a cascading if-else-if
. The second switch mirrors that in the original source code, but substitutes the case labels with their corresponding positions. This two-step process makes it easy to preserve the flow control of the original switch.
Switches in the JVM
For more technical depth on switch
, you can refer to the JVM Specification, where the compilation of switch statements is described. In a nutshell, there are two different JVM instructions that can be used for a switch, depending on the sparsity of the constants used by the cases. Both depend on using integer constants for each case to execute efficiently.
If the constants are dense, they are used as an index (after subtracting the lowest value) into a table of instruction pointers—the tableswitch
instruction.
If the constants are sparse, a binary search for the correct case is performed—the lookupswitch
instruction.
In de-sugaring a switch
on String
objects, both instructions are likely to be used. The lookupswitch
is suitable for the first switch on hash codes to find the original position of the case. The resulting ordinal is a natural fit for a tableswitch
.
Both instructions require the integer constants assigned to each case to be sorted at compile time. At runtime, while the O(1)
performance of tableswitch
generally appears better than the O(log(n))
performance of lookupswitch
, it requires some analysis to determine whether the table is dense enough to justify the space–time tradeoff. Bill Venners wrote a great article that covers this in more detail, along with an under-the-hood look at other Java flow control instructions.
Before JDK 7
Prior to JDK 7, enum
could approximate a String
-based switch. This uses the static valueOf
method generated by the compiler on every enum
type. For example:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
Best Answer
Because
println
is an instance method of thePrintStream
class, and you need an instance of a class to call instance methods.However,
System.out
is an instance ofPrintStream
, so you can do:or you can create a new
PrintStream
instance, for example to write to a file:This section in the Java Tutorial can be helpful: Lesson: Classes and Objects