GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Para que serve o static{ ... }


#1

public class MyStatic {
	static {
		// code ...
	}
}

Eu andei vendo isso em códigos de terceiros em Java e .NET C#, e não entedi como funciona e para que serve, os atributos static eu entendo, fazem parte da classe e não de uma instancia, mas esse codigo eu não entendi, alguém pode me explicar ?

Obrigado.


#2

Estas com sorte eu estou estudando para a prova SCJP, e ainda estou nos primeiros capitulos, mas é o seguinte

public class olapessoal
{
static {
}
}

isto chama-se bloco de inicialização estatico da classe
tipo para inicializar as variaveis de instancia normalmente faz-se isso

int a=3;
mas se quisermos por
int a=3 *(Math.sqrt(34)/44)-Math.exp(9);
visto que esta forma de inicializar a variavel de instançia fica ja um pouco confusa porque a expressão é grande, então dai podemos inicializar nos construtores ou blocos de inicialização.
mas usando os blocos estaticos de inicialização ai não temos que por o mesmo codigo em todos os construtores da classe.
se tem um codigo que estara em todos os construtores ai é boa oportunidade para usar blocos de inicialização, os blocos de inicialização podem ser ou não estatico
mas a linguagem java tem muitas coisas, mas devemos apenas usar aquilo que realmente precisamos e que torna o nosso codigo claro, por isso não acho muito bom por
varios blocos estaticos de inicialização na classe,

e ja ia esquecendo o bloco de inicialização estatico é executado sempre antes de todos os construtores, e se um bloco de inicialização lança uma excepção verificada, então ai todos os construtores devem lançar esta execpção,


#3

o que o sulito disse está correto, só complementando...

na ordem é executado da seguinte forma:

primeiro os blocos estaticos das classes mães, avós, etc,começando pela mais acima até chegar a classe sendo usada.

depois disso os blocos não estaticos.

depois os construtores.

os blocos estaticos são executados uma unica vez quando a classe vai para a memoria, enquanto que os não estaticos são executados cada vez que você instancia a classe.

bom, se não me engano é isso.


#4

è mesmo isso não te enganaste, a ordem é esta.


#5

sulito,
poderia explicar essa parte : e se um bloco de inicialização lança uma excepção verificada, então ai todos os construtores devem lançar esta execpção.
talvez com algum exemplo.
também to estudando pra scjp.


#6

É o seguinte, vou ser o mais sincero possivel, eu li isso num livro e ficou o conceito na cabeça, mas nunca testei excepções em blocos estatico , mas prometo que vou fazer uns testes e ainda amanha eu tenho uma exemplo montado, porque eu tambem estou a estudar para o scjp e não quero e nem vou deixar passar nenhuma duvida :idea: :smile: .
e se eu não encontrar um exemplo no livro, vamos enviar um email para a editora e o autor, para explicarem melhor


#7

Caso um bloco static lance um exception ... ela será encpsulada em uma java.lang.ExceptionInInitializerError .....


#8

E é dai que saem as ExceptionInInitializerError que são tão dificeis de se diagnosticar.

A não ser que o código seja seu.


#9

Entendi e vou realizar alguns testes e debugar para ver a execução, mas existe blocos não estaticos ?? como seria a sintaxe ??

Valew.


#10

Eu fiz assim por intuição e funcionou, esta correto somente colocar as chaves no bloco nao-estatico ? ( linha 14 )

public class MyBlockTest{
	/*
	 * STATIC BLOCK
	 */
	static{	
		System.out.println("STATIC RUN - MyBlockTest");		
	}
	/*
	 * NON-STATIC BLOCK
	 */
	{
		System.out.println("NON-STATIC RUN - MyBlockTest");
	}
	/**
	 * Construtor Padrao
	 */
	public MyBlockTest(){
		System.out.println("CONSTRUCTOR - MyBlockTest");
	}
}

public class MyBlockTestChildren extends MyBlockTest{
	/*
	 * STATIC BLOCK
	 */
	static{	
		System.out.println("STATIC RUN - MyBlockTestChildren");		
	}
	/*
	 * NON-STATIC BLOCK
	 */
	{
		System.out.println("NON-STATIC RUN - MyBlockTestChildren");
	}
	/**
	 * Construtor Padrao
	 */
	public MyBlockTestChildren(){
		System.out.println("CONSTRUCTOR - MyBlockTestChildren");
	}
}

Execução:

public class Main {
	/**
	 * @param args
	 */
	public static void main(String[] args) {		
		MyBlockTest my1 = new MyBlockTestChildren();
		MyBlockTest my2 = new MyBlockTestChildren();
	}
}

Output:

STATIC RUN - MyBlockTest
STATIC RUN - MyBlockTestChildren
NON-STATIC RUN - MyBlockTest
CONSTRUCTOR - MyBlockTest
NON-STATIC RUN - MyBlockTestChildren
CONSTRUCTOR - MyBlockTestChildren
NON-STATIC RUN - MyBlockTest
CONSTRUCTOR - MyBlockTest
NON-STATIC RUN - MyBlockTestChildren
CONSTRUCTOR - MyBlockTestChildren

Ele pasou pelo bloco estatico da super classe e depois da subclasse uma vez na criação da primeira instancia , e depois ele passa pelo bloco nao-estatico e depois pelo construtor toda vez que instancio um objeto da classe.

Valews.


#11

O pessoal todo perdeu o foco da conversa explicar como se usa os blocos de inicialização e dar exemplo ja esta mais que resolvido :smile: , mas agora surgiu outro problema que me fez passar a noite em claro :roll: :? , eu li num livro o seguinte:

mas vou postar exactamente como esta no livro

Um bloco de inicialização pode lançar uma exeção verificada somente se todos os construtores das classes declararem lançar a mesma execeção
o problema é que o livro tem esta frase mas não tem exemplo e dai que eu quero testar para ver se isso é veridico, e desde ontem que eu tento lançar uma execção num bloco de inicialização e sem sucesso. precisamos de um exemplo que funcione para esclarecer isso, e ou o livro esta errado ou é problema da tradução do livro, porque o original deste livro é em ingles

os dados do livro:

TITULO: A linguagem de programação java (quarta edição)
autores: Ken Arnold , James Gosling, David Holmes
editora:bookman
tradução: MARIA LUCIA BLANCK LISBOA
capa:


a pagina onde tirei a frase foi a pagina 73 no tema 2.5.2-blocos de inicialização

e principalmente para o pessoal que esta a estudar para scjp que é o meu caso devemos descobrir o que se passa :idea:

devemos conseguir um exemplo que mostra uma exeção lançada por um bloco de inicialização, ou então o pessoal que escreveu ou traduziu o livro se enganou
e mais uma dica o livro não se referia a [b]

Membro desde: 21/05/2007 12:14:11
Mensagens: 72
Offline
Caso um bloco static lance um exception ... ela será encpsulada em uma java.lang.ExceptionInInitializerError ..... [/b] axo eu


#12

veja o exemplo dessa classe abaixo:

package pacote;
import java.sql.SQLException;
public class Classe {
	public static int numero = 0;
	static{
		System.out.println("bloco estatico");
	}
	{
		System.out.println("\nbloco comum");
		numero++;
		if (numero % 2 == 1){
			throw new SQLException("a cada vez impar que instanciar o objeto vai dar problema");
		}
	}
	public Classe()throws SQLException{
		System.out.println(numero);
	}
	public Classe(String palavra)throws SQLException{
		System.out.println(palavra);
	}
	public Classe(int parametroNumero)throws SQLException{
		System.out.println(parametroNumero);
	}
	public static void main(String[] args) {
		for (int i=0;i<10;i++){
			try{
				new Classe();
			}catch(Exception e){
				System.out.println("mensagem da exceção: "+e.getMessage());
			}
		}
	}
}

se você tirar o throws de qualquer um dos construtores a classe simplesmente não compila, conforme o livro que você disse fala, então não é erro de tradução, esta correto isso mesmo, se um bloco lançar exceção, o construtor precisa declara-la.

Lembrando que exceção não verificada são as filhas, netas etc, de RuntimeException, as que tiverem na arvore de herança dela, estas podem ser lançadas, mas se você lançar uma que seja verificada (não filha de RuntimeException), precisará dar o throws nos construtores, se você mudar a exceção lançada no bloco da classe que eu postei para IllegalArgumentException, ai ja vai compilar mesmo tirando a declaração da exceção no construtor..

eu também tinha duvida quanto a isso, então resolvi testar...rs


#13

calminha ai irmão :? :idea: , assim não vale não,
deves por uma excepção verificada no construtor ( ex: Exception) , e o SQLException é verificada tens toda a razão, mas nos exemplos que eu utilizava eu tentava com o Exception e não funcionava tipo:

public class erro {
	int a;
	{
		throw new Exception("aqui devia dar para aceitar isso");
	}
	public erro() throws Exception
	{
		a=33;
	}
	public erro(int a) throws Exception
	{
		this.a=a;
	}
}

isto tambem devia funcionar mas não funciona, com o sqlexception que usaste funciona lindamente com com o exception nao funciona, por isso a duvida ainda continua, porque eu tenho tentando com o exception e nada desde ontem


#14

Agora embassou. .!! rs, mas estamos aqui para aprender.

Eu fiz os testes no Eclipse ( utilizo a jdk1.6.0_12 ):

No bloco estatico não consegui lançar uma Exception, a não ser que eu colocasse num bloco try:

/*
 * STATIC BLOCK
*/
static{			
	System.out.println("STATIC RUN - MyBlockTest");	
	try{
		throw new Exception();			
	}
	catch(Exception e){	
		e.printStackTrace();
	}
}

No bloco não estático, só consegui lancar a excecao se colocar um condicional ( linha 07 ) e colocar a clausula throws nos construtores:

/*
* NON-STATIC BLOCK
*/
{
	System.out.println("NON-STATIC RUN - MyBlockTest");
	if(true)	
		throw new Exception();		
}
/**
 * Construtor Padrao
 * @throws Exception 
 */
public MyBlockTest() throws Exception{
	System.out.println("CONSTRUCTOR - MyBlockTest");
}

E ai no main tenho que colocar o try:

/**
 * @param args	
 */
public static void main(String[] args) {	
	try{		
		MyBlockTest my1 = new MyBlockTestChildren();
		MyBlockTest my2 = new MyBlockTestChildren();
	}catch(Exception e){
		e.printStackTrace();
	}	
}

output:
java.lang.Exception
STATIC RUN - MyBlockTest

at estudo.objects.MyBlockTest.<clinit>(MyBlockTest.java:28)
at estudo.main.Main.main(Main.java:44)

NON-STATIC RUN - MyBlockTest
java.lang.Exception
at estudo.objects.MyBlockTest.(MyBlockTest.java:43)
at estudo.main.Main.main(Main.java:44)

colocando a clausula throws no metodo main:

public static void main(String[] args) throws Exception {	
		MyBlockTest my1 = new MyBlockTest();
		MyBlockTest my2 = new MyBlockTest();	
}

output:
STATIC RUN - MyBlockTest
NON-STATIC RUN - MyBlockTest
java.lang.Exception
at estudo.objects.MyBlockTest.(MyBlockTest.java:28)
at estudo.main.Main.main(Main.java:44)
Exception in thread "main" java.lang.Exception
at estudo.objects.MyBlockTest.(MyBlockTest.java:43)
at estudo.main.Main.main(Main.java:44)

Interessante.

Valews.


#15

[quote=sulito]calminha ai irmão :? :idea: , assim não vale não,
deves por uma excepção verificada no construtor ( ex: Exception) , e o SQLException é verificada tens toda a razão, mas nos exemplos que eu utilizava eu tentava com o Exception e não funcionava tipo:

public class erro {
	int a;
	{
		throw new Exception("aqui devia dar para aceitar isso");
	}
	public erro() throws Exception
	{
		a=33;
	}
	public erro(int a) throws Exception
	{
		this.a=a;
	}
}

isto tambem devia funcionar mas não funciona, com o sqlexception que usaste funciona lindamente com com o exception nao funciona, por isso a duvida ainda continua, porque eu tenho tentando com o exception e nada desde ontem[/quote]

Compilei e rodei usando o jdk 1.5.0_22, compilou e rodou tranquilamente. Veja se o teu erro não está em quem está instanciando essa classe.


#16

eu nem instanciei apenas compilei e deu erro. :frowning: o stracktrace é

agora vamos fazer o seguinte os que testaram e compilou dizem que compilou e os que não compilou dizem que não, e vamos ver quantos compilou e quantos não compilou


#17

mas pondo desta forma compilou e o livro esta certo :smile: :smiley:

    public class erro {  
        int a;  
        {  
              if(true)
            throw new Exception("aqui devia dar para aceitar isso");  
        }  
        public erro() throws Exception  
       {  
           a=33;  
       }  
       public erro(int a) throws Exception  
       {  
           this.a=a;  
       }  
  }

mas agora surge mais outro problema, como é que no pc do Bruno Laturner
compilou e no meu não????? eu tentei compilar no java 6 e no java 7, porque eu uso os 2


#18

talvez o java 6 tenha algum tipo de trava, onde ele não irá compilar quando identificar que a exceção sempre irá ocorrer... coisa que talvez o java 1.5 não deve fazer (de acordo com o relato do Bruno)...

algo semelhante a quando você fazer algo assim:

return 12;
x = 20;//da um erro dizendo que essa linha nunca será alcançada.

claro que isso é só um chute...não posso te afirmar isso com certeza...

mas se isso for o que estou "chutando" mesmo, ja é uma particularidade dessa versão do compilador, na especificação da linguagem, o que é referente aos blocos de código, é aquilo do construtor ter que declarar a exceção mesmo mesmo...


#19

quanto ao que disseste eu tambem acho que tens toda a razão, porque até ja notei jdk6 e 7 que eu uso não deixa mesmo por codigo assim

return 2;
x++;

parece que o compilador rejeita para não ter codigo desnessecario que nunca ira correr.
mas estou a baixar o jdk 5 ( custou encontrar visto que é antigo) mas quando eu instalar vou testar o codigo e se funcionar então o tema estara resolvido :smile:


#20