Enums

Baseado em um probleminha que tivemos aqui no trabalho e só depois de um tempinho fomos entender. :stuck_out_tongue:

O que será impresso primeiro, “Construtor” ou “static”? E porquê?

public enum EnumTeste{
    TESTE(1);
    static {
        System.out.println("static");
    }
    EnumTeste(int i){
        System.out.println("Construtor");
    }
    public static String teste(){
        return "teste";
    }
}

public class Teste {
    public static void main(String[] args){
        System.out.println(EnumTeste.teste());
    }
}

Quando rodei o programa acima com a opção -verbose, vi o seguinte:

[Loaded Teste from file:/C:/temp2/java/]
[Loaded java.lang.Enum from shared objects file]
[Loaded EnumTeste from file:/C:/temp2/java/]
Construtor
static
teste
...

Ou seja, ele carregou a classe Teste (para poder executar a função “teste”), a seguir a classe java.lang.Enum (que é a superclasse de EnumTeste e de todas as outras Enums) e então executou o teste.

Dá a nítida impressão que ele faz o seguinte:

  • As constantes enums são definidas (é como se fosse executado algo como “public static enum EnumTeste Teste = new Teste (1)” na definição da enum)
  • A seguir, os blocos static são executados.

É um pouco inesperado, já que você pensaria o contrário (primeiro o static e depois os enums), mas faz algum sentido se o bloco static depender de algum enum já estar inicializado.

Muito Interessante!

Mais explicitamente, citando a Java Language Specification:

Ou seja, ele inicializa as constantes (chamando os construtores se necessário), e então executa o bloco static.

ue???

Nas classes sao diferentes…

Eu costumo fazer isso com algumas enums por aqui e funciona muito bem

public enum TipoSanguineo {
	A,
	B,
	AB,
	O;
	
	private static Map<String, TipoSanguineo> relations;
	
	public static TipoSanguineo byValue(String abo){
		return relations.get(abo);
	}
	
	static {
		relations = new HashMap<String, TipoSanguineo>();
		relations.put("A", A);
		relations.put("B", B);
		relations.put("AB", AB);
		relations.put("O", O);
	}
}

Faço isso quando tenho as constantes como constraints no banco de dados, por exemplo, e preciso converter para enums dentro dos objetos persistidos (usando JDBC).

Muito bom, gostei. Só o nome do método que poderia ser diferente né? getByName, getByString - acho byValue meio confuso.

Muito bom, gostei. Só o nome do método que poderia ser diferente né? getByName, getByString - acho byValue meio confuso.[/quote]

Hum, pois é… seguindo sua idéia, talvez eu faça um refactoring para getByString().

blocos static sao carregados junto com a class, entao ele é executado antes de qualquer coisa… por isso…
experimente aqui

class Tes{
static{System.out.println("static");}
{System.out.println("nonstatic");}
public static void main(String ar[]){
Test t = new Test();
}}

flw!