Ajuda com método genérico e elegante

Estou construindo um projetinho pessoal aqui, e eu fiz uma classe com constantes, que está funcionando corretamente (abaixo)…

[code]package model;

import java.awt.Color;
import java.io.IOException;
import java.util.Properties;

enum Type {
STRING,
INT,
HEXA
}

public class Constants {

private static final Properties CONFIG_PROPERTIES = loadConfig("/model/config/config.properties");

public static final String WINDOW_TITLE = (String)loadProperty("window.title", Type.STRING);
public static final int WINDOW_WIDTH = (Integer)loadProperty("window.width", Type.INT);
public static final int WINDOW_HEIGHT = (Integer)loadProperty("window.height", Type.INT);
public static final int NUM_BUFFERS = (Integer)loadProperty("num.buffers", Type.INT);
public static final int FPS = (Integer)loadProperty("fps", Type.INT);
public static final Color BORDER_COLOR = new Color((Integer)loadProperty("border.color", Type.HEXA));
public static final Color BACKGROUND_COLOR = new Color((Integer)loadProperty("background.color", Type.HEXA));

private static Properties loadConfig(String configFileName) {
	Properties props = new Properties();
	try {
		props.load(Object.class.getResourceAsStream(configFileName));
	} catch (IOException e) {
		e.printStackTrace();
		System.exit(0);
	}
	return props;
}

private static Object loadProperty(String key, Type type) {
	String value = CONFIG_PROPERTIES.getProperty(key);
	Object property = null;
	try{
		switch(type){
			case STRING:
				property = value;
				break;
			case INT:
				property = Integer.parseInt(value);
				break;
			case HEXA:
				property = Integer.parseInt(value, 16);
				break;
		}
	} catch(Exception e) {
		System.err.println("Erro ao carregar a propriedade "+key);
		e.printStackTrace();
		System.exit(0);
	}
	return property;
}

}[/code]
O que me deixa desconfortável é essa “gambi” na função loadProperty(), onde eu tenho que informar o tipo de dado que eu quero para realizar a operação necessária sobre o String de valor, e depois realizar um casting sobre o Object retornado.

Assim, quem pode me ajudar a construir um método generic que consiga retornar o tipo de dado correto e saber qual operação realizar internamente sobre o String de valor? Ah, sem utilizar aquele enum e, sendo possível, utilizando um código mais elegante…

Uma assinatura assim, eu imaginei…

private static <T> T loadProperty(String key) { /** código **/ }
Já verifiquei em um teste que o método consegue substituir o <T> na compilação de acordo com o tipo da variável que recebe o resultado do método…

Ex:

public static final int WINDOW_WIDTH = loadProperty("window.width");

Em tempo de compilação o <T> será substituído por Integer, já que o tipo da variável WINDOW_WIDTH é int. Só que dentro do método eu não consigo fazer um teste do tipo T instanceof Integer, nem chamar algo específico como T.parseInt(value)… realmente não faz sentido…

Então como eu posso fazer? Alguém aí que manda bem em Generics pode me ajudar?

:wink:

Ola

Vc até consegue fazer isto usando o generics, mas teria que passar o tipo de dado que vc quer receber… tipo, a ssinatura teria que mudar para:

private static <T> T loadProperty(T a, String key)

O List faz isto no metodo )]toArray

Realmente, não dá pra saber o tipo do parâmetro em tempo de execução. O que pode ser feito é adicionar um parâmetro ao método do tipo Class<T>, e ao chamar o método, passar o tipo da classe.

Ficaria assim:

private static &lt;T&gt; T loadProperty(String key, Class&lt;T&gt; type) { /** código **/ }
E, ao chamar o método:

loadProperty("window.width", Integer.class);

Abraços

A reification do java 7 visa resolver esse problema. Enquanto ela não chega, passar o parâmetro do tipo Class<T> é a melhor solução.

[quote=tnaires]Realmente, não dá pra saber o tipo do parâmetro em tempo de execução. O que pode ser feito é adicionar um parâmetro ao método do tipo Class<T>, e ao chamar o método, passar o tipo da classe.

Ficaria assim:

private static &lt;T&gt; T loadProperty(String key, Class&lt;T&gt; type) { /** código **/ }
E, ao chamar o método:

loadProperty("window.width", Integer.class);

Abraços[/quote]
Interessante, gostei…

Eu nem sabia que isso era um problema!

:stuck_out_tongue:

[size=18][color=olive]Opá, grave suas propriedades já informando o tipo de cada variável no arquivo de configuração, assim você sempre irá saber o que esta lendo.
:mrgreen:
[/color][/size]

[quote=LottaLava][size=18][color=olive]Opá, grave suas propriedades já informando o tipo de cada variável no arquivo de configuração, assim você sempre irá saber o que esta lendo.
:mrgreen:
[/color][/size]
[/quote]
É até interessante fazer assim, eu já havia até pensado nisso…

Mas tudo que abre margem pro usuário fazer Hgada tira a robustez da aplicação, que precisa ser resistente a Hgadas…

Além disso eu gostaria de ver uma implementação utilizando Generics… mas o pessoal aqui já deu boas idéias…

Só pra constar, segue em anexo um jar auto-executável do “pograminha”, é uma animaçãozinha simples para estudar detecção de colisões…

Requer Java 5.

Contém fontes!