Static Blocks vs Instance Blocks: Everything you need to know

Understanding static and instance blocks
Let me explain about static and instance blocks. You might already have heard of static blocks and also have used it. But what are instance blocks? What is the difference between static and instance blocks? When to use them? I'll give you an answer for all of these questions. Let's tackle them one by one.


Static block

A static block is a  block that is executed only once. Yes, you heard it right. You might already be familiar with the static keyword that anything declared static isn't a part of the object. So, a static block similarly contains code that executes only one time no matter how many times you create an object for that class. Now, you can already estimate what you might want to write in a static block. If you didn't, let me give you an example, loading the driver classes in JDBC. You need to do them only once, throughout the entire program. Fine, now you got an idea of what is a static block. Let us talk about some facts of static blocks.

1. Static block gets executed every time when the class loads into memory not every time an object is created.
2. You cannot declare methods in the static block, however you can use labeled blocks for code classification.
3. Static block executes in the main thread.
4. The variables you declare in a static block aren't a part of the object.
5. They are not even the static variables of the class, they just belong to that block only.
6. You cannot access non-static variables/methods of that class directly, you need to create an object.
7. You can make method calls in a static block.
8. Static blocks are executed in the order they are written.

An example of static block


class StaticBlock
{
static int i=10;

static
{
    System.out.println("my static block 1");

    // You can use labeled blocks inside static

blocks
    printingThread:{

    // static block is executed in main thread
    System.out.println("Current thread

"+Thread.currentThread());
    }

}

static{

    System.out.println("In static block "+i);

    // you can call main() too
    main("");

    // You can also execute threads
    new Thread(new Runnable(){
        public void run()
        {
            for(int i=1;i<=5;i++)

System.out.println(Thread.currentThread().getName()+"

"+i);
        }
    },"First thread").start();
   
    // You can't do this, myMeth() is non-static
    // myMeth();
}

    public void myMeth()
    {
    System.out.println("In a non static method");
    }

    public static void main(String ...args)
    {
    System.out.println("In main()");
    }
}

Output of StaticBlock


my static block 1
Current thread Thread[main,5,main]
In static block 10
In main()
In main()
First thread 1
First thread 2
First thread 3
First thread 4
First thread 5

Note: To access myMeth(), you need to create an object new StaticBlock().myMeth(); works, though the method is private, because it is written in the same class.

Instance blocks

Instance blocks are different. Unlike static blocks, they execute every time you create an object for a class. Now, you might have understood what you need to write in these instance blocks. The instance block contains code that needs to execute every time an object is created no matter through which constructor. There will mostly be things that you need to do when a class' object is created, the one you will write in common in all the constructors. Most programmers would write that common code in a method and call it each constructor. Doesn't it seem to be an old practice? The instance block does this for you. It executes just before the constructor is executed and just after the super() is called (after the super class' constructor is activated). The concept of instance blocks is best applied in anonymous inner classes, where we cannot declare a constructor.


class MyBlock
{
    public MyBlock()
    {
    System.out.println("My block");
    }
}
class InstanceBlock extends MyBlock
{
   
    public InstanceBlock()
    {
    System.out.println("In the constructor");
    }

    public InstanceBlock(String st)
    {
    System.out.println(st);
    }
   
    {
        System.out.println("instance block 1");
        labeledBlock:{
            System.out.println("labeled block in

instance block 1");
        }
    }

    {
    System.out.println("instance block 2");
    }

   
    public static void main(String args[])
    {
        System.out.println("In main()");
   
        // Instance blocks are executed twice here
        // because two objects are being created
        new InstanceBlock();
        new InstanceBlock("Second constructor");

        // Instance blocks in anonymous inner classes
        new Thread(new Runnable(){
        int i;
            {
            i=1;
            }
            public void run(){
                while(i<=5){               

                System.out.println("run "+i);
                i++;
                }
            }
        }).start();

    }
}    

Output of InstanceBlock


In main()
My block
instance block 1
labeled block in instance block 1
instance block 2
In the constructor
My block
instance block 1
labeled block in instance block 1
instance block 2
Second constructor
run 1
run 2
run 3
run 4
run 5

Double Brace Initialization

Double brace initialization is using the instance blocks in the anonymous inner classes as done in the previous program. See one more example,


        ArrayList<String> as=new ArrayList<String>(){
            {
            add("Foo");
            add("Bar");
            }
        };

The simple snippet does the entire thing, it creates an ArrayList<String> object and adds elements. This is a much cleaner way of writing than the routine way.

Thanks for reading. If this post did you a favor, please share it.

No comments: