Método static{} - como funciona?

8 respostas
mateusviccari
Olá, vi essa classe
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hibernateUtil;

import beans.Cliente;
import beans.Socio;
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.AnnotationConfiguration;  
import org.hibernate.cfg.Configuration;  
  
public class ConnectDB {  
      
    private static final SessionFactory sessionFactory;      
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();  
      
    static {  
        try{                    
  
            Configuration configuration = new AnnotationConfiguration()  
            .addAnnotatedClass(Cliente.class)
            .addAnnotatedClass(Socio.class);
              
            configuration.setProperty("hibernate.connection.url","jdbc:postgresql://localhost:5432/testeFrameworkAtualy");  
            configuration.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver");  
            configuration.setProperty("hibernate.connection.username", "postgres");  
            configuration.setProperty("hibernate.connection.password","masterkey");
              
            sessionFactory = configuration.buildSessionFactory();  
  
        }catch (Throwable t){  
            throw new ExceptionInInitializerError(t);  
        }  
    }  
      
    public static Session getInstance(){  
        Session session = (Session) threadLocal.get();  
        session = sessionFactory.openSession();  
        threadLocal.set(session);          
        return session;  
    }  
      
}
E reparei que aquilo que está dentro do static{} é executado quando eu crio uma instancia da classe ou quando eu chamo o método estatico getInstance... Mas não entendi como é o contexto de execução desse "método"... alguem me da uma luz?

8 Respostas

gabrielmskate

Esse é um bloco estático… Ele é executado com a classe, é a primeira coisa que é executada…

Pra saber mais da uma lida aqui: http://mballem.wordpress.com/2011/01/26/static-x-instance/

[]'s

E

O Java sempre trabalha com o conceito de “não deixe para antes o que você pode fazer na hora” :slight_smile: - mais conhecido como “preparar a declaração do Imposto de Renda na noite do dia 30 de abril”.

Ele deveria ter um nome brasileiro em vez de um nome da Indonésia :slight_smile:

Portanto, uma classe só é carregada quando você precisa dela, e seu código só é compilado depois de ter sido interpretados algumas vezes (tipicamente 1000 vezes).

É por isso que um programa costuma demorar para executar algum código que nunca foi executado antes, mas depois que a classe foi carregada, ele fica mais rápido.

No seu caso, um código “static {}” é executado quando a classe for carregada - ou usando Class.forName, que carrega uma classe, ou criando a primeira instância dessa classe, ou então chamando algum método estático dessa classe pela primeira vez. Na verdade, quando você escreve:

class X {
    static int y = 2;
    static String s = "bla";
}

está escrevendo algo equivalente a:

class X {
    static int y;
    static String s;
    static {
        y = 2;
        s = "bla";
    }
}

e é por isso que a ordem de declaração dos membros pode ser importante, se um valor for dependente de outros valores na mesma classe.

mateusviccari

entanglement:
O Java sempre trabalha com o conceito de “não deixe para antes o que você pode fazer na hora” :slight_smile: - mais conhecido como “preparar a declaração do Imposto de Renda na noite do dia 30 de abril”.

Ele deveria ter um nome brasileiro em vez de um nome da Indonésia :slight_smile:

Portanto, uma classe só é carregada quando você precisa dela, e seu código só é compilado depois de ter sido interpretados algumas vezes (tipicamente 1000 vezes).

É por isso que um programa costuma demorar para executar algum código que nunca foi executado antes, mas depois que a classe foi carregada, ele fica mais rápido.

No seu caso, um código “static {}” é executado quando a classe for carregada - ou usando Class.forName, que carrega uma classe, ou criando a primeira instância dessa classe, ou então chamando algum método estático dessa classe pela primeira vez. Na verdade, quando você escreve:

class X {
    static int y = 2;
    static String s = "bla";
}

está escrevendo algo equivalente a:

class X {
    static int y;
    static String s;
    static {
        y = 2;
        s = "bla";
    }
}

e é por isso que a ordem de declaração dos membros pode ser importante, se um valor for dependente de outros valores na mesma classe.

ENTANGLEMENT, quer dizer que, quando eu escrevo isso aqui:

class X { static int y = 2; static String s = "bla"; }
Essas 2 variaveis NÃO serão inicializadas no momento em que a JVM inicia?
E a JVM vai inicializar essas variaveis somente quando a classe for referenciada de algum lugar?
E isso inclui uma chamada a, por exemplo, um Class c=X.class ou será somente na instanciação de um novo objeto do tipo X ou a chamada de algum metodo estatico?

E

É isso mesmo. Explique a saída do seguinte programa.

class CarregadaApenasQuandoReferenciada {
    public static int get(String nome) {
		System.out.println ("Classe " + CarregadaApenasQuandoReferenciada.class.getName() + " carregada por " + nome);
	    return 0;
	}
	static {
	    z = get("z"); 
	}
    public static int x = get("x");
    public static int y = get("y");
	public static int z;
}

class TesteBlocoStatic {
    public static void main (String[] args) throws Exception {
		System.out.println ("Classe " + TesteBlocoStatic.class.getName() + " carregada");
		Class.forName ("CarregadaApenasQuandoReferenciada");
	}
}

Ele imprime (quando invocado como “java -cp . TesteBlocoStatic”) :

Classe TesteBlocoStatic carregada
Classe CarregadaApenasQuandoReferenciada carregada por z
Classe CarregadaApenasQuandoReferenciada carregada por x
Classe CarregadaApenasQuandoReferenciada carregada por y
E

Se a classe fosse inicializada quando a JVM fosse inicializada, ou seja, antes do main, você teria a seguinte saída:

Classe CarregadaApenasQuandoReferenciada carregada por z  
    Classe CarregadaApenasQuandoReferenciada carregada por x  
    Classe CarregadaApenasQuandoReferenciada carregada por y  
    Classe TesteBlocoStatic carregada
E

Agora me explique por que a saída é “z x y”, em vez de “x y z” já que os membros estão na ordem “x y z”.

E

Note que apenas puxar uma classe, com .class, não a inicializa. Mude o programa para:

public static void main (String[] args) throws Exception {
		System.out.println ("Classe " + TesteBlocoStatic.class.getName() + " carregada");
		CarregadaApenasQuandoReferenciada.class.getName();
	}
    }

Você vai ver que

Classe CarregadaApenasQuandoReferenciada carregada por z
Classe CarregadaApenasQuandoReferenciada carregada por x
Classe CarregadaApenasQuandoReferenciada carregada por y

não é impresso. (Dica: http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String,%20boolean,%20java.lang.ClassLoader) , com o segundo parâmetro = false, também tem o mesmo comportamento. Que tal dar uma olhadinha na documentação? )

mateusviccari

Putz, muito obrigado, entendi tudo…

Criado 10 de maio de 2012
Ultima resposta 10 de mai. de 2012
Respostas 8
Participantes 3