Criei um método que extrai dados de uma tabela de strings e gera uma lista de objetos, usando reflexão. O problema é que, até o momento, meu método retorna uma lista de Object, queria saber se é possível que ele retorne uma lista do tipo passado como parâmetro diretamente. Segue meu código abaixo.
Obrigado pela ajuda!
protected List<Object> getObjectsFromTable(
List<List<String>> table,
Class<?> type,
String[] fields_names,
Class<?>[] fields_types)
throws Throwable {
/* Pega os setters do objeto. */
Method[] methods = new Method[fields_names.length];
for (int i = 0; i < fields_names.length; i++) {
String field_name = fields_names[i];
String method_name = "set" + Character.toUpperCase(field_name.charAt(0)) +
field_name.substring(1);
methods[i] = type.getMethod(method_name, new Class<?>[]{fields_types[i]});
}
List<Object> result = new ArrayList<Object>();
/* Percorre as linhas da tabela. */
ListIterator<List<String>> i = table.listIterator();
while (i.hasNext()) {
/* Nova instância do objeto. */
Object aux = type.newInstance();
/* Pega os campos da linha atual. */
List<String> campos = i.next();
ListIterator<String> j = campos.listIterator();
for (int index = 0; index < fields_names.length; index++) {
String campo = j.next().toUpperCase();
Class<?> tipo = fields_types[index];
if (tipo == String.class) {
methods[index].invoke(aux, campo);
} else if (tipo == long.class) {
methods[index].invoke(aux, Long.parseLong(campo));
} else if (tipo == int.class) {
methods[index].invoke(aux, Integer.parseInt(campo));
} else {
throw new IllegalArgumentException("Invalid type!");
}
}
result.add(aux);
}
return result;
}
Criei um método que extrai dados de uma tabela de strings e gera uma lista de objetos, usando reflexão. O problema é que, até o momento, meu método retorna uma lista de Object, queria saber se é possível que ele retorne uma lista do tipo passado como parâmetro diretamente. Segue meu código abaixo.
Obrigado pela ajuda!
[/quote]
retorne uma lista do tipo passado como parâmetro diretamente “isso me parace meio redundante”.
Exatamente… na verdade, eu formulei mal a pergunta: eu queria passar o tipo uma única vez como parâmetro generics e já retornar a lista desse tipo. O melhor que consegui até agora foi isso:
protected static <T> List<T> getObjectsFromTable(
List<List<String>> table,
Class<? extends T> type,
String[] fields_names,
Class<?>[] fields_types)
throws Throwable {
/* Pega os setters do objeto. */
Method[] methods = new Method[fields_names.length];
for (int i = 0; i < fields_names.length; i++) {
String field_name = fields_names[i];
String method_name = "set" + Character.toUpperCase(field_name.charAt(0)) +
field_name.substring(1);
methods[i] = type.getMethod(method_name, new Class<?>[]{fields_types[i]});
}
List<T> result = new ArrayList<T>();
/* Percorre as linhas da tabela. */
ListIterator<List<String>> i = table.listIterator();
while (i.hasNext()) {
/* Nova instância do objeto. */
T aux = type.newInstance();
/* Pega os campos da linha atual. */
List<String> campos = i.next();
ListIterator<String> j = campos.listIterator();
for (int index = 0; index < fields_names.length; index++) {
String campo = j.next().toUpperCase();
Class<?> tipo = fields_types[index];
if (tipo == String.class) {
methods[index].invoke(aux, campo);
} else if (tipo == long.class) {
methods[index].invoke(aux, Long.parseLong(campo));
} else if (tipo == int.class) {
methods[index].invoke(aux, Integer.parseInt(campo));
} else {
throw new IllegalArgumentException("Invalid type!");
}
}
result.add(aux);
}
return result;
}
O problema é que eu precisso passar e type, para poder usar reflection dentro do método, o que é redundante. Como eu poderia pegar T.class?
Sim, tem que ser redundante. Um é para o compilador saber o tipo e o outro é para que a sua lógica saiba o tipo. O compilador não é capaz de ver a sua lógica, e o type-erasure impede que a sua lógica veja o generic do compilador. Por isso tem que ser redundante.
Quiçá o java 7 resolve esse problema com reification. ERASE THE ERASURE!
Sim, tem que ser redundante. Um é para o compilador saber o tipo e o outro é para que a sua lógica saiba o tipo. O compilador não é capaz de ver a sua lógica, e o type-erasure impede que a sua lógica veja o generic do compilador. Por isso tem que ser redundante.
Quiçá o java 7 resolve esse problema com reification. ERASE THE ERASURE![/quote]
:arrow: Contraditório então pela a afirmação do Paulo Silveira, citado acima ???
Sim, tem que ser redundante. Um é para o compilador saber o tipo e o outro é para que a sua lógica saiba o tipo. O compilador não é capaz de ver a sua lógica, e o type-erasure impede que a sua lógica veja o generic do compilador. Por isso tem que ser redundante.
Quiçá o java 7 resolve esse problema com reification. ERASE THE ERASURE![/quote]
:arrow: Contraditório então pela a afirmação do Paulo Silveira, citado acima ???[/quote]
Não, não é contraditório.
Ele tem que passar e type, algo que é redundante porque o é para o compilador entender e type é para a lógica do programa entender.
Não dá, no java 6, para fazer sem ser redundante. Você não pode instanciar um generic ou descobri-los por reflection porque eles são perdidos na compilação. Não estão lá nos bytecodes. A “gambiarra” para colocá-los nos bytecodes é colocar o type, um Class explícito com o qual você pode trabalhar na lógica do seu programa. O problema é que isso duplica o tipo, uma vez que e type são na verdade a mesma coisa. E como não é possível fazer o compilador entender o type, apenas o , você é obrigado a colocar os dois.
Mas, no java 7, está planejado a reificação dos generics, que basicamente faz com que o exista nos bytecodes e que por isso possa ser visto no reflection. Isso elimina a necessidade de existir o type e elimina a necessidade de haver redundância.
[quote=victorwss]…Sim…(…)…
…(…)…
…Mas, no java 7, está planejado a reificação dos generics, que basicamente faz com que o exista nos bytecodes e que por isso possa ser visto no reflection. Isso elimina a necessidade de existir o type e elimina a necessidade de haver redundância…[/quote]
:thumbup: Bom, eu não sei porque uma afirmação e depois algo que vem a ser de uso favorável em sua colocação, entretando acho que o Paulo Silveira poderia melhor informar no seu blog, pois simplesmente ele direciona para uma pagina http://gafter.blogspot.com/2006/11/reified-generics-for-java.html , que depois contradiz tudo sobre o que, vem a ser uma coisa para Java 5 e outra evolução no Java 7.
bem Marcio, nao consegui entender direito o que voce escreveu. Acho que voce nao percebeu que eu e o Victor estamos falando a MESMA coisa: eu no blog e ele naquela frase. O movimento erase the erasure teria de criar um SEGUNDO tipo de generics, ja que o generics da maneira atual que foi implementada, atraves de erasures, NAO DA para pegar o tipo generico em tempo de execucao.
Pra eles colocarem a reificacao, tera de criar esse segundo tipo de generics (sugerido como em vez de ) . Esse sim seria atraves de reificacao, que nao existe hoje.
Repetindo a minha afirmacao mais claramente: hoje em dia, com o generics como esta, nao da para fazer isso. E nem vai dar sem criar um OUTRO generics. Eles nao vao fazer o mesmo pois seria uma quebra de compatibilidade (nao da pra por reificacao em cima de erasure sem quebra de compatibilidade, nao vao fazer isso, como ja afirmaram).
[quote=victorwss]
Mas, no java 7, está planejado a reificação dos generics, que basicamente faz com que o exista nos bytecodes e que por isso possa ser visto no reflection. Isso elimina a necessidade de existir o type e elimina a necessidade de haver redundância.[/quote]
Isso, mas nao sera a mesma sintaxe.
E infelizmente nao esta planejado, estao pensando mas muita gente fala que nao vai ter.
[quote=Paulo Silveira]
bem Marcio, (…)
(…)… tipo generico em tempo de execucao.
Pra eles colocarem a reificacao, tera de criar esse segundo tipo de generics (sugerido como em vez de ) . Esse sim seria atraves de reificacao, que nao existe hoje.
Repetindo a minha afirmacao mais claramente: hoje em dia, com o generics como esta, nao da para fazer isso. E nem vai dar sem criar um OUTRO generics. Eles nao vao fazer o mesmo pois seria uma quebra de compatibilidade (nao da pra por reificacao em cima de erasure sem quebra de compatibilidade, nao vao fazer isso, como ja afirmaram).[/quote]
:thumbup: Ficou mais esclarecido, porque estava acreditando que a reificação já era algo aprimorado sobre que fora colocado ao Java 7, mas já que ainda não existe,a informação do victor virou tese.