views:

203

answers:

6

The entry point into a program in java is typically something like this


    // MyMain.java
    public class MyMain{  
      //whatever 
        public static void main(String args[]){ 
        System.out.println("balderdash");
        }
    }
However, since there is only the one SOP in main, the above class may be like this instead

    // MyMain.java
    public class MyMain{
        //whatever
        static {    
        System.out.println("balderdash");
        }
    }

One obvious advantage to using main(...) is that arguments may be passed in to the program. Another ( I'm guessing here ) may have to do with the garbage collecter treating objects created within a static block differently.

What other benefits come from using the language-defined entry-point - public static void main( String args[] ) instead of using a static initializer.

p.s. The above snippets are for illustration only, and may not be compilable

+5  A: 

You can call main() for other objects from anywhere else in your code as many times as you want. A static initializer is only going to ever run once. Also, you can pass parameters from the command line into main().

Two big plusses for main() in my book.

banjollity
Another big plus: every java programmer clearly understands that a class with main method is executable. Static initializer is kind of obfuscation.
Andreas_D
but we may also achieve parameter passing by say, defining a properties file and reading it explicitly
Everyone
@Everyone: For every simple solution, there is an infinite number of complex ones. ;)
Aaron Digulla
+5  A: 
  • You can test it or call it from other applications.
  • It's what other people will expect.
  • If you execute your whole application in the context of a static initializer, I suspect you'll effectively be holding a lock on that type for the whole time. If any other thread tries to call a static method in the same class, it will block. That's the sort of problem you get when you try to use a concept in an unexpected way - it's just conceptually "wrong". Initializing the class simply isn't the same as running an application.

EDIT: Here's an example of that problem:

class SampleTask implements Runnable
{
    public void run()
    {
        System.out.println("Calling someStaticMethod");
        Test.someStaticMethod();
        System.out.println("someStaticMethod returned");
    }
}

public class Test
{
    static
    {
        System.out.println("Starting new thread...");
        new Thread(new SampleTask()).start();
        System.out.println("Thread started. Sleeping");
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            System.out.println("Interrupted!");
        }
        System.out.println("Finished sleeping");          
    }

    public static void someStaticMethod()
    {
        System.out.println("In someStaticMethod");
    }

    public static void main(String[] args)
    {
        System.out.println("In main. Sleeping again.");
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            System.out.println("Interrupted!");
        }
    }
}

Output:

Starting new thread...
Thread started. Sleeping
Calling someStaticMethod
Finished sleeping
In someStaticMethod
someStaticMethod returned
In main. Sleeping again.

Note how the call to someStaticMethod from the new thread has to wait until the static initializer has finished before it gets to run.

Jon Skeet
No, static initializers do not have any inherent synchronization. You're not implicitly holding a lock inside a static initializer.
Jesper
Section 12.4.2 of the JLS suggests otherwise. Will try to come up with an example.
Jon Skeet
@Jesper: Static initializers are run from a classloader during the class init step. This code is guaranteed to be synchronized.
Aaron Digulla
@Jesper: Otherwise, it would be possible to get a partially uninitialized class and work with that. At the same time, final static constants are set, so they wouldn't be valid, either.
Aaron Digulla
Also see this question: http://stackoverflow.com/questions/878577/are-java-static-initializers-thread-safe
Aaron Digulla
There's an example of this kind of deadlock in Gafter and Bloch's Java Puzzlers.
Tom Hawtin - tackline
+2  A: 

The main reason why it's better to use main() is that you can have several main methods in your application (in different classes). If you load a class, main() isn't executed automatically while static code blocks are always executed exactly once at the first time a class is loaded and there is no way to prevent that.

Aaron Digulla
+1  A: 

Let's not forget about maintainability. When someone else goes to change your code they are always going to look for a main() method to start the program. Unless there is some reason you can't get around (and I'm guessing there is not) then I would just use the main method.

Ben
+2  A: 

OK, I'll admit that I haven't tried it with a static initialized class, but wouldn't typing

java StaticInitializedClass

on the command line print out

Exception in thread "main" java.lang.NoSuchMethodError: main

since it doesn't have a main(String[]) method?

R. Bemrose
Normaly you got the Exception, but you can end the static initializer with System.exit() to avoid the Exception... but IMO this just make all worse, at least you would not be able to use the class somewhere else.
Carlos Heuberger
A: 

If you don't have any entry point, you cannot run anything. If you have many entry points (many main methods), user who starts your application controls which will be run by command line.
On the other hand static initialization blocks are executed when class is loaded. Controlling which class is loaded and the order of class loading (and of executing their static initialization blocks) is much harder to control. That's enough reason not to put to much logic to static initialization blocks. You make something harder to read and understand and in reward you receive something harder to use.

Tadeusz Kopec