57

I’m Looking for a definitive answer from a primary or secondary source for why (notably) Java and C# decided to have a static method as their entry point, rather than representing an application instance by an instance of an Application class (with the entry point being an appropriate constructor).


Background and details of my prior research

This has been asked before. Unfortunately, the existing answers are merely begging the question. In particular, the following answers don’t satisfy me, as I deem them incorrect:

  • There would be ambiguity if the constructor were overloaded. – In fact, C# (as well as C and C++) allows different signatures for Main so the same potential ambiguity exists, and is dealt with.
  • A static method means no objects can be instantiated before so order of initialisation is clear. – This is just factually wrong, some objects are instantiated before (e.g. in a static constructor).
  • So they can be invoked by the runtime without having to instantiate a parent object. – This is no answer at all.

Just to justify further why I think this is a valid and interesting question:

  • Many frameworks do use classes to represent applications, and constructors as entry points. For instance, the VB.NET application framework uses a dedicated main dialog (and its constructor) as the entry point1.

  • Neither Java nor C# technically need a main method. Well, C# needs one to compile, but Java not even that. And in neither case is it needed for execution. So this doesn’t appear to be a technical restriction. And, as I mentioned in the first paragraph, for a mere convention it seems oddly unfitting with the general design principle of Java and C#.

To be clear, there isn’t a specific disadvantage to having a static main method, it’s just distinctly odd, which made me wonder if there was some technical rationale behind it.

I’m interested in a definitive answer from a primary or secondary source, not mere speculations.


1 Although there is a callback (Startup) which may intercept this.

18
  • 4
    @mjfgates Also, I had hoped to have made it clear that this is not simply “why didn’t people do it the way I want”, and that I’m genuinely interested in the reasons. Commented Jul 10, 2012 at 21:11
  • 2
    For Java I'd think the reasoning is simple: When developing Java, they knew that most people learning the language would know C/C++ beforehand. Hence Java not only looks a lot like C/C++ instead of say smalltalk, but also took over idiosynchrasies from C/C++ (just think of octal integer literals). Since c/c++ both use a main method, doing the same for java made sense from that point of view.
    – Voo
    Commented Jul 10, 2012 at 21:15
  • 5
    @Jarrod You’re unfair. I thought I had made it quite clearly not into a rant. “not constructive”? How so? I’m explicitly asking for references, not just wild discussions. You are of course free to disagree that this is an interesting question. But if this kind of questions is OT here, I really fail to see what purpose Programmers.SE serves. Commented Jul 10, 2012 at 21:46
  • 2
    Relevant Meta discussion.
    – yannis
    Commented Jul 10, 2012 at 22:10
  • 3
    Question: If it is an application object, Don't you need two things. 1) A constructor. 2) A method on the object to run your application. The constructor must complete for the object to be valid and thus run-able. Commented Jul 11, 2012 at 7:40

8 Answers 8

39

TL;DR

In Java, the reason of public static void main(String[] args) is that

  1. Gosling wanted
  2. the code written by someone experienced in C (not in Java)
  3. to be executed by someone used to running PostScript on NeWS

https://i.sstatic.net/qcmzP.png

 
For C#, the reasoning is transitively similar so to speak. Language designers kept the program entry point syntax familiar for programmers coming from Java. As C# architect Anders Hejlsberg puts it,

...our approach with C# has simply been to offer an alternative... to Java programmers...

 

Long version

expanding above and backed up with boring references.

 

java Terminator Hasta la vista Baby!

VM Spec, 2.17.1 Virtual Machine Start-up

...The manner in which the initial class is specified to the Java virtual machine is beyond the scope of this specification, but it is typical, in host environments that use command lines, for the fully qualified name of the class to be specified as a command-line argument and for subsequent command-line arguments to be used as strings to be provided as the argument to the method main. For example, using Sun's Java 2 SDK for Solaris, the command line

java Terminator Hasta la vista Baby!

will start a Java virtual machine by invoking the method main of class Terminator (a class in an unnamed package) and passing it an array containing the four strings "Hasta", "la", "vista", and "Baby!"...

...see also: Appendix: I need your clothes, your boots and your motorcycle

  • My interpretation:
    execution targeted for use like typical scripts in command line interface.

 

important sidestep

...that helps avoid a couple of false traces in our investigation.

VM Spec, 1.2 The Java Virtual Machine

The Java virtual machine knows nothing of the Java programming language...

I noticed above when studying prior chapter - 1.1 History which I thought could be helpful (but turned out useless).

  • My interpretation:
    execution is governed by VM spec alone, which
    explicitly declares that it has nothing to do with Java language
    => OK to ignore JLS and anything Java language related at all

 

Gosling: a compromise between C and scripting language...

Based on above, I began searching the web for JVM history. Didn't help, too much garbage in results.

Then, I recalled legends about Gosling and narrowed down my search to Gosling JVM history.

Eureka! How The JVM Spec Came To Be

In this keynote from the JVM Languages Summit 2008, James Gosling discusses... Java's creation,... a compromise between C and scripting language...

  • My interpretation:
    explicit declaration that at the moment of creation,
    C and scripting have been considered most important influences.
     
    Already seen nod to scripting in VM Spec 2.17.1,
    command line arguments sufficiently explain String[] args
    but static and main aren't there yet, need to dig further...

Note while typing this - connecting C, scripting and VM Spec 1.2 with its nothing-of-Java - I feel like something familiar, something... object oriented is slowly passing away. Take my hand and keep movin' Don't slow down we're nearly there now

Keynote slides are available online: 20_Gosling_keynote.pdf, quite convenient for copying key points.

    page 3
    
        The Prehistory of Java
        * What shaped my thinking
    
    page 9
    
        NeWS
        * Networked Extensible Window System
        * A window system based on scripting....
          PostScript (!!)
    
    page 16
    
        A Big (but quiet) Goal:
          How close could I get to a
          "scripting" feel...
    
    page 19
    
        The original concept
        * Was all about building
          networks of things,
          orchestrated by a scripting
          language
        * (Unix shells, AppleScript, ...)
    
    page 20
    
        A Wolf in Sheeps Clothing
        * C syntax to make developers
          comfortable

A-ha! Let's look closer at C syntax.

The "hello, world" example...

main()
{
    printf("hello, world\n");
}

...a function named main is being defined. The main function serves a special purpose in C programs; the run-time environment calls the main function to begin program execution.

...The main function actually has two arguments, int argc and char *argv[], respectively, which can be used to handle command line arguments...

Are we getting closer? you bet. It is also worth following "main" link from above quote:

the main function is where a program starts execution. It is responsible for the high-level organization of the program's functionality, and typically has access to the command arguments given to the program when it was executed.

  • My interpretation:
    To be comfortable for C developer, program entry point has to be main.
    Also, since Java requires any method to be in class, Class.main is
    as close as it gets: static invocation, just class name and dot,
    no constructors please - C knows nothing like that.
     
    This also transitively applies to C#, taking into account
    the idea of easy migration to it from Java.

Readers thinking that familiar program entry point doesn't matter are kindly invited to search and check Stack Overflow questions where guys coming from Java SE are trying to write Hello World for Java ME MIDP. Note MIDP entry point has no main nor static.

 

Conclusion

Based on above I would say that static, main and String[] args were at the moments of Java and C# creation most reasonable choices to define program entry point.

 

Appendix: I need your clothes, your boots and your motorcycle

Have to admit, reading VM Spec 2.17.1 was enormous fun.

...the command line

java Terminator Hasta la vista Baby!

will start a Java virtual machine by invoking the method main of class Terminator (a class in an unnamed package) and passing it an array containing the four strings "Hasta", "la", "vista", and "Baby!".

We now outline the steps the virtual machine may take to execute Terminator, as an example of the loading, linking, and initialization processes that are described further in later sections.

The initial attempt... discovers that the class Terminator is not loaded...

After Terminator is loaded, it must be initialized before main can be invoked, and a type (class or interface) must always be linked before it is initialized. Linking (§2.17.3) involves verification, preparation, and (optionally) resolution...

Verification (§2.17.3) checks that the loaded representation of Terminator is well formed...

Resolution (§2.17.3) is the process of checking symbolic references from class Terminator...

 
Symbolic references from Terminator oh yeah.

2
  • 2
    For some reason I had a hard time believing that "modernity" was an actual word.
    – someguy
    Commented Jul 20, 2012 at 16:26
  • @Songo story of the answer is also like a movie. It has been first posted at meta, in a discussion of question closure: "If the question would be reopened, I'd probably write an answer like below..." Then it was used to back up appeal to reopen and finally moved here
    – gnat
    Commented Nov 29, 2013 at 16:01
15

That just feels vaguely abusive to me. A constructor is used for the initialization of an object: it sets up an object, which is then used by the code that created it.

If you put basic usage functionality inside of the constructor, and then never actually use the object that the constructor creates in external code, then you're violating the principles of OOP. Basically, doing something really weird for no apparent reason.

Why would you want to do that anyway?

3
  • 7
    But isn’t the “application instance” logically an object? Why would that be abusive? As for using the object – it has one purpose: representing the running application. Sounds very SoC-y to me. “Why would you want to do that?” – I’m merely interested in the rationale for the decision since I find it at odds with the rest of the mentality. Commented Jul 10, 2012 at 21:41
  • 8
    @KonradRudolph: A constructor, like a property getter, is generally expected to complete in a bounded time without waiting for some asynchronous event (like user input) to occur. It would be possible to have a constructor which launched a main application thread, but that adds a level of complexity which may not be needed for all applications. Requiring that a console application that simply prints "Hello world" to standard output should spawn an extra thread would be goofy. Using a Main method works well for the simple case, and isn't really a problem in harder cases, so why not?
    – supercat
    Commented Jul 11, 2012 at 6:45
  • -1 for you're violating the principles of OOP. I would have disagreed had you quoted a specific principle but not downvoted as to sustain dialogue.
    – Vorac
    Commented Sep 28, 2020 at 19:01
9

For Java I'd think the reasoning is simple: When developing Java, the devs knew that most people learning the language would know C/C++ beforehand.

Hence Java not only looks a lot like C/C++ instead of say smalltalk, but also took over idiosynchrasies from C/C++ (just think of octal integer literals). Since c/c++ both use a main method, doing the same for java made sense from that point of view.

I'm pretty sure I remember bloch or someone saying something along this lines about why they added octal integer literals, I'll see if I can find some sources :)

6
  • 2
    If looking the same as C++ was so much important for Java, why did they for example change : to extends? And public static void main(String [ ] args) inside a class is quite different than int main(int argc, char **argv) outside of a class.
    – svick
    Commented Jul 10, 2012 at 22:19
  • 2
    @svick One possibility: Java introduced interfaces and clearly they wanted to separate the two concepts (inheriting interfaces/classes) - with just one "keyword" that won't work. And "quite different"? It's the nearest possible mapping of it and so far I've never seen a c++ programmer have a problem understanding that the static main method is the entry point. Contrary to that having a class called Application or something whose constructor is used, is something that would look strange to most c++ programmers.
    – Voo
    Commented Jul 11, 2012 at 0:33
  • @svick int in c to void in java had to with how a return code from an application was generated - in java, its 0 unless System.exit(int) is invoked. The change of parameters has to do with how arrays of strings are passed in each language. Everything in java is in a class - there is no option to have it elsewhere. Changing : to extends is a matter of syntax and are essentially the same. All else is dictated by the language.
    – user40980
    Commented Jul 11, 2012 at 20:08
  • @MichaelT But all those are design decisions that make Java different from C++. So why would be keeping Java the same as C++ be important in the case of main(), when it apparently wasn't important enough in other cases.
    – svick
    Commented Jul 11, 2012 at 20:32
  • @svick Except that it's perfectly ok to not return anything from main in C too and such trivialities would hardly confuse anyone anyhow. The point wasn't to recreate c++ and all its mistakes but only to make the programmer more at home. What do you think a C++ programmer will have an easier time reading: Java or objective-c code? What do you think will look more obvious to a C++ programmer a main method or a constructor of some class as entry point?
    – Voo
    Commented Jul 11, 2012 at 20:35
6

Well, there're lots of main functions out there which just run an infinite loop. A constructor working this way (with an object that never gets constructed) is what seems odd to me.

There're so many funny things about this concept. Your logic running on top of a unborn object, objects that born to die (since they do all their job in the constructor), ...

Wouldn't all these side effects gonna corrupt much more the OO wagon than a simple public (because it needs to be accessed by an unknown) static (because no instance is needed for us to get started) void main (because it's the entry point)?

For a simple, plain, function entry point to exist in Java, public and static would automatically be required. Although being a static method, it boils down to what we can get more near of a plain function to accomplish what's wanted: a simple entry point.

If you are not going to adopt a simple, plain, function entry point as an entry point. What's next that doesn't seems odd as a contructor that's not meant to construct?

1
  • 1
    I'd say the problem was not having first-class functions. Sticking the main() inside an object (that isn't instantiated before the main gets called) is a bit of an anti-pattern. Maybe they should have an "application" object that gets constructed and runs its non-static main() method, then you can put startup initialisation in the constructor, and it would feel a lot better than having static methods, though a simple top-=level main() fn would be good too. Static main is a bit of a kludge all in all.
    – gbjbaanb
    Commented Jul 20, 2012 at 15:55
4

You can quickly run some standalone tests on a class, during development, by sticking a main() in the class you're trying to test.

1
  • 1
    This to me is probably the most compelling reason, as it also allows multiple entry points during development for testing different configurations, etc.
    – cgull
    Commented Jul 11, 2012 at 23:57
0

You've got to start somewhere. A static main is the simplest execution environment you can have -- no instance of anything (outside of the JVM and the simple string parameters) needs to be created -- so it can "come up" with a minimum of fuss (and low likelihood of a coding error preventing startup, etc) and can do simple things without a lot of other setup.

Basically an application of KISS.

[And, of course, the main reason is: Why not?]

3
  • 3
    As I said, I’m not convinced by that at all. Objects do get instantiated before, and code gets executed before. It’d need a quote from one of the original developers to convince me that this was the reason. Commented Jul 10, 2012 at 21:38
  • 2
    The amount of work necessary to instantiate a class from C code is pretty much identical to calling a static method.. You even have to do the same checks (does the class exist? fine, does it have a public constructor with the right signature? fine then go ahead).
    – Voo
    Commented Jul 10, 2012 at 21:42
  • No user object needs to be created. The object constructor is not executed. The API is blazingly simple. And it's the easiest to understand. Commented Jul 12, 2012 at 1:47
0

To my understanding the primary reason is simple. Sun was a Unix company selling Unix machines and Unix is what the C "main(args)" convention for invoking a binary was designed for.

Additionally Java was explicitly designed to be easy to pick up for C and C++ programmers, so there was no good reason for not just simply picking up the C convention.

The chosen approach where every class can have an invocation method is quite flexible, especially in combination with the Main-Classline in the MANIFEST.MF file in a runnable jar.

1
  • Of course, the jar file wasn't invented until much later. Commented Jul 12, 2012 at 1:47
-1

It is not consistent with OOP philosophy that a program would be an object from an OS process point of view, as there is no way to have more than one by definition.

On top of that, a constructor isn't an entry point by any means.

It seems to me like the most reasonable choice to have main as a static function, which it actually is at the end of the day. Given the architecture of VMs such as JVM and CLR, any other choice would be unnecessarily pushing it.

4
  • 1
    I think you are wrong there. It is possible to have more than one process, hence more than one object. Incidentally, this is entirely equivalent to instantiating Runnable objects to have multiple threads. Commented Jul 20, 2012 at 16:27
  • A process is a running program, and you can only start a process once via one entry point. Threads have their own entry points but are still within the same process. Commented Jul 20, 2012 at 16:30
  • 1
    Like I said below someguy’s answer, this isn’t relevant. What’s relevant is logical consistency. Logically, processes are represented as objects by the launcher (OS, JVM, whatever) and are initialised. Commented Jul 20, 2012 at 16:42
  • @KonradRudolph True, but the initialization of a program is only one part of the initialization of a process, and doesn't legitimize a program constructor. Commented Jul 21, 2012 at 21:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.