Método static{} - como funciona?

Olá, vi essa classe

[code]
/*

  • 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;  
}  

} [/code]
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?

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

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.

[quote=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.

[/quote]

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?

É 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

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  

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”.

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? )

Putz, muito obrigado, entendi tudo…