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.

Konrad Rudolph
  • 13,059
  • 4
  • 55
  • 75
  • 1
    @mjfgates I fear that, yet the problem interested me enough to see if somebody actually knows an answer. After all, there are people from the C# design team active on Stack Overflow, and maybe some old Java buff sees this. – Konrad Rudolph Jul 10 '12 at 21:09
  • 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. – Konrad Rudolph Jul 10 '12 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 Jul 10 '12 at 21:15
  • 1
    @Voo If I had a reliable source for this statement I’d consider the question answered. – Konrad Rudolph Jul 10 '12 at 21:22
  • 1
    So you say that it makes more sense to have execution start in the constructor of an `Application` class. The problem with this is you're now restricting the type of "runnable" programs to a single class! As it stands, I can make a class `MaryHadALittleLamb` and make it "runnable" just by giving it a Main. You might then say, well ok, it should derive from Application, but in languages with only single inheritance, that too is a very big restriction. –  Jul 10 '12 at 21:23
  • 1
    @MgSam I don’t follow. I’m not saying “you should derive from Application” – but even if, that would not be a disadvantage at all (it’s arguably even an advantage to tag the entry point via an interface or inheritance). – Konrad Rudolph Jul 10 '12 at 21:44
  • Of the 15 up votes that @mjfgates got on their comment why aren't there at least 5 close votes on this ranty not constructive question? –  Jul 10 '12 at 21:45
  • 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. – Konrad Rudolph Jul 10 '12 at 21:46
  • @JarrodRoberson The comment got most of it's upvotes on Stack Overflow, where the question was originally asked. – yannis Jul 10 '12 at 22:07
  • 2
    Relevant [Meta discussion](http://meta.programmers.stackexchange.com/questions/3768/what-is-not-constructive). – yannis Jul 10 '12 at 22:10
  • @KonradRudolph this is reworded slightly better, and slightly more on topic on programmers, but still comes off as your ranty opinion on why *( in your opinion )* others made *mistakes* in these implementations you asking for justifications for other peoples design choices and decisions that can't be answered definitively. If they could it would be very easily Googled, which you would of already found the answer quickly, therefore all this is going to generate, even on programmers is speculation and supposition ( this is what all the answers currently are ) and no true *answer*. –  Jul 11 '12 at 04:28
  • 1
    @JarrodRoberson Quick note, we had to clear the close votes, because something went awry with the rejection of the migration, check the Meta discussion I've linked to - and perhaps post your Meta comments as a full answer there? – yannis Jul 11 '12 at 04:32
  • 1
    *"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."* this comment from an answer below kind of proves you aren't going to get the answer you want unless you contact the original designers in question, anyone else is going to be speculating; this is still **not constructive** and **off topic** even with the attempt at re-wording it. –  Jul 11 '12 at 04:33
  • @YannisRizos about the up votes, if most of them came from SO that is even *more* disappointing of the community. –  Jul 11 '12 at 04:41
  • 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. – Martin York Jul 11 '12 at 07:40
  • @Loki I thought the constructor might just run the application, but I’m slowly getting convinced by this argument. Which bodes badly for this question because it’s then operating on a false premise. – Konrad Rudolph Jul 11 '12 at 09:20
  • 1
    @ChrisF Thanks for adding the note, that should help. – Konrad Rudolph Jul 20 '12 at 16:26
  • 1
    @KonradRudolph by the way regarding your preference for _different_ approach, I for one see nothing wrong with it. As mentioned in [my answer](http://programmers.stackexchange.com/a/157606/31260), in Java ME MIDP entry point is an instance method of `MIDlet` object; it works just fine - with the only caveat of frequently being harder to start with for those used to old-fashioned `static main` – gnat Jul 20 '12 at 21:55

8 Answers8

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.stack.imgur.com/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.

gnat
  • 21,442
  • 29
  • 112
  • 288
  • 2
    For some reason I had a hard time believing that "modernity" was an actual word. – someguy Jul 20 '12 at 16:26
  • @Songo story of the answer is also like a movie. It has been first [posted at meta](http://meta.programmers.stackexchange.com/posts/3811/revisions), 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 Nov 29 '13 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?

Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
  • 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](http://en.wikipedia.org/wiki/Separation_of_concerns)-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. – Konrad Rudolph Jul 10 '12 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 Jul 11 '12 at 06: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 Sep 28 '20 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 :)

Voo
  • 765
  • 6
  • 11
  • 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 Jul 10 '12 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 Jul 11 '12 at 00: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. –  Jul 11 '12 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 Jul 11 '12 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 Jul 11 '12 at 20:35
  • @svick In running an application from the console, one needs an entry point for a console application to start running (on shouldn't start running an arbitrary function). That entry point needs to take a a structure that is most simply defined as array of strings (arguments) presented on the command line. That this method is named main in both C and Java and is a convention followed in many other languages (see http://en.wikipedia.org/wiki/Main_function ). –  Jul 11 '12 at 21:12
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?

oblitum
  • 168
  • 6
  • 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 Jul 20 '12 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.

Graham Borland
  • 809
  • 6
  • 7
  • 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 Jul 11 '12 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?]

Daniel R Hicks
  • 240
  • 1
  • 6
  • 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. – Konrad Rudolph Jul 10 '12 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 Jul 10 '12 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. – Daniel R Hicks Jul 12 '12 at 01: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.

gnat
  • 21,442
  • 29
  • 112
  • 288
-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.

Yam Marcovic
  • 9,270
  • 2
  • 27
  • 29
  • 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. – Konrad Rudolph Jul 20 '12 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. – Yam Marcovic Jul 20 '12 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. – Konrad Rudolph Jul 20 '12 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. – Yam Marcovic Jul 21 '12 at 21:47