What is the use of nested blocks in Java?

10

I saw something written similar to the code below. Does this second block in the method method have any use? Can it be used in any way?

I ran this code and it compiled and appeared only the First print. message, not displaying Second print. .

I've seen something like try ... catch ... finally, but this is not the same case.

If it can be used in any way, does someone write me a practical example?

public class BlocoAninhado {

    public static void main(String[] argumentos) {
        BlocoAninhado.metodo();
    }

    public static void metodo() {
        System.out.println("Primeiro print.");
    }

    {
        System.out.println("Segundo print.");
    }
}
    
asked by anonymous 08.03.2014 / 02:10

3 answers

8

The example block you gave is a Instance Initializer for a purpose other than a simple one block of scope. Whenever you find these loose blocks within the body of a class, this is about it, not the variable scope blocks.

A brother of the Instance Initializer is the Static Initializer :

public class BlocoAninhado {

    public static void main(String[] argumentos) {
        BlocoAninhado.metodo();
    }

    public static void metodo() {
        System.out.println("Segundo print.");
    }

    static {
        System.out.println("Primeiro print.");
    }
}

This should run, and the block in your example does not execute because an instance of that class is not created. The Static Initializer runs because it is not bound to the instance, just like any static method.

The other case of loose blocks is the common ones that you find inside the functions, these are blocks of scope. A common and useful use of them is in case s of the switch command:

switch(foo) {
  case BAR: {
    int x;
  }
  break;

  case BAZ: {
    char x; //usando o mesmo nome sem problemas.
  }
  break;
}

For illustration, this would make the type of block you are using run:

public class BlocoAninhado {

    public static void main(String[] argumentos) {
        (new BlocoAninhado()).metodo();
    }

    public static void metodo() {
        System.out.println("Segundo print.");
    }

    {
        System.out.println("Primeiro print.");
    }
}
    
08.03.2014 / 03:47
3

Java blocks have multiple applications

Body classes and methods

Class:

class C { ... }

Method:

void m() { ... }

Inline implementations:

Runnable r = new Runnable() {
    public void run() { ... }
};

Group declarations in conditionals, loops, and exceptional control

Conditional:

if (cond) { ... } else { ... }
switch (valor) { case 1: ...; break; default: ...}

Ties:

while (cond) { ... }
do { ... } while (cond)
for (...) { ... }

Exceptional control and shutdown:

try { ... } catch { ... } finally { ... }

Arbitrary Blocks

They are placed in the middle of the code and follow the normal flow of execution, but with a scope of their own, which means that the declared variables will no longer exist at closing.

int a = 1;
{
    int b = a + 2; //b == 3
}
//b não existe mais

This is probably allowed for a language issue, that is, a block can replace a valid command in Java grammar. This greatly simplifies the implementation because the compiler does not need to perform a special check to allow blocks only in specific commands.

Labels

You can use the break <label> command to stop execution of a specific block.

I have not been able to think of any practical application, so here's an example without even the slightest sense:

int a = 1;
myLabel: {
    for (int i = 0; i < 20; i++) {
        a++;
        if (a == 5) {
            break myLabel;
        }
    }
    System.out.println("Não vai imprimir isso!");
}
System.out.println(a);

Instance and class initializers

Instance (runs before builder):

classe C {
    { ... }
}

Static (executes when class is loaded on first use:

classe C {
    static { ... }
}

The order of execution

An interesting question about the initialization blocks is about the order in which they are executed, whereas there is the object constructor and attribute initializations.

Consider the following example:

public class Initializations {
    static class X {
        static int y(String str) { 
            System.out.println("y(" + str + ")");
            return 1;
        }
    }
    static class A {
        static { 
            System.out.println("static initializer A"); 
        }
    static int y = X.y("static A");
    int y2 = X.y("instance A");
        { 
            System.out.println("instance initializer A"); 
        }
        public A() {
            System.out.println("constructor A");
        }
    }
    static class B extends A {
        static int y = X.y("static B");
        int y2 = X.y("instance B");
        static { 
            System.out.println("static initializer B"); 
        }
        { 
            System.out.println("instance initializer B"); 
        }
        public B() {
            System.out.println("constructor B");
        }
        public void imprime() {
            System.out.println("imprime()");
        }
    }
    public static void main(String[] args) {
        System.out.println("init main");
        new B().imprime();
        System.out.println("end main");
    }
}

I will comment on the result produced by the above code:

  • init main : the first item is of method main , so the subclasses were not initialized.
  • static initializer A : when executing new B() Java executes the static parent initializer of the parent class first.
  • y(static A) : then the static attribute y of class A was initialized.
  • y(static B) : then the static attribute y of class B was initialized.
  • static initializer B : now, yes the static initializer of B .
  • y(instance A) : now the instance attribute y2 of class A .
  • instance initializer A : now the instance initializer of class A .
  • constructor A : and the A constructor.
  • y(instance B) : now the instance attribute y2 of class B .
  • instance initializer B : and the instance initializer of B .
  • constructor B : ending the initialization sequence, Java executes the constructor of B .
  • imprime() : and the instance method is called.
  • end main : finally the main method ends.
  • Based on this, we can say that the order of execution is:

  • Static variables and initializers, starting from the parent class and ending with the child, and in the order they are declared in the body of each class in the hierarchy.
  • Beginning once again in the parent class and ending in the child, instantiation initializers, instance initializers, and constructors are executed in this order.
  • 10.03.2014 / 20:59
    2

    This is mainly used to declare that a variable belongs only to that scope. For example:

    public class Teste{
    
      public static void main(String[] args){
        Teste.imprime();
      }
    
      public static void imprime(){
        {
          int i = 0;
          System.out.println(i);
        }
        {
          int i = 2;
          System.out.println(i);
        }
      }
    }
    

    You will be able to successfully compile and output:

    0
    2
    

    However, if you reverse, for example, the order of the rows in the second block:

    public class Teste{
    
      public static void main(String[] args){
        Teste.imprime();
      }
    
      public static void imprime(){
        {
          int i = 0;
          System.out.println(i);
        }
        {
          System.out.println(i);
          int i = 2;
        }
      }
    }
    

    You will receive the following, for this code, the following compile error:

    Teste.java:13: error: cannot find symbol
                            System.out.println(i);
                                               ^
    

    That is, it serves as a very primary form of encapsulation , restricting only access to the block it belongs to.

        
    08.03.2014 / 03:28