Reflection noSuchFieldException [resolvido]

11 respostas
D

Estou fazendo uma classe genérica que implementa comparable, mas ta complicado… vejam o código e o resultado:
code

@SuppressWarnings("unchecked")
    @Override
    public int compare(T obj1, T obj2) {
	System.out.println(obj1);
	System.out.println(obj2);
	
	T entity1 = (T) obj1;
	T entity2 = (T) obj2;
	
	System.out.println(entity1);
	System.out.println(entity2);
	
	System.out.println(obj1.getClass().getName());
	System.out.println(entity1.getClass().getName());
        try {
            Object value1 = entity1.getClass().getField(this.sortField).get(entity1);
//erro na linha de cima

resul

65 - aff3 -  - Crédito
64 - aff2 -  - Crédito
65 - aff3 -  - Crédito
64 - aff2 -  - Crédito
br.com.noronha.model.entity.Grupo
br.com.noronha.model.entity.Grupo
java.lang.NoSuchFieldException: descricao
	at java.lang.Class.getField(Class.java:1537)
	at br.com.noronha.infra.abstractt.LazySorter.compare(LazySorter.java:33)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:325)
	at java.util.TimSort.sort(TimSort.java:189)
	at java.util.TimSort.sort(TimSort.java:173)

bom, coloquei o monte de syso
e fiz o casting para o T pq achei que poderia receber um object e por isso dava esse erro.
Mas como podem ver no console aí…
ta certinho!!!

minha classe possui sim, o field:

private String descricao;

podem ajudar?

11 Respostas

R

pode tirar o cast.

Cadê o valor de sortField?

D

“descricao”

R

Era só ler a documentação do método. Ele não vai encontrar o Field porque o método getField só busca atributos públicos

D

verdade. Desculpe pelo erro.
Mas não faz muito sentido.
Não concorda?

R

d34d_d3v1l:
verdade. Desculpe pelo erro.
Mas não faz muito sentido.
Não concorda?

Eu acho que faz sim.

Acessar atributos privados via reflection é uma péssima prática, e bastante propensa a erros. Portanto uma maneira de acessar somente os atributos públicos é bastante interessante.

Agora você também pode acessar os Fields que não são públicos se quiser, pode usar o método getDeclaredField

D

Eu acabei criando um ReflectUtil
com o seguinte método:

public static <T> Object getFieldValue(T obj, String field) throws Exception{
	Object value = null;
	
	String method = "get" + field.substring(0, 1).toUpperCase()  
                  + field.substring(1);  

              Method m = obj.getClass().getDeclaredMethod(method);  
              value = (Object) m.invoke(obj);  
          
          return value;
    }
R

Bom essa é uma solução, mas existe outra. Já ouviu falar da Mirror DSL?

Ela foi criada justamente pra evitar o ReflectionUtil que existe em quase todos os projetos :slight_smile:

D

Rodrigo Sasaki:
Bom essa é uma solução, mas existe outra. Já ouviu falar da Mirror DSL?

Ela foi criada justamente pra evitar o ReflectionUtil que existe em quase todos os projetos :)

eu já tinha visto…
é legal… fica muito mais limpo o código.

Mas por exemplo, este método

public static Field getPrimaryKeyField(Class<?> type) {

	for (Field f : type.getDeclaredFields()) {
	    if (f.isAnnotationPresent(Id.class)) {
		return f;
	    }
	}

	return null;
    }

pode ser reproduzido?

pois eu vi ali: http://projetos.vidageek.net/mirror/annotations/reflecting/
eu pego as anotações, mas o que eu quero fazer é o inverso … kkkk

R

Ué, pra mim parece correto.

Ele vai varrer todos os Fields da classe, e se algum estiver anotado com @Id, ele será retornado.

A
d34d_d3v1l:
Rodrigo Sasaki:
Bom essa é uma solução, mas existe outra. Já ouviu falar da Mirror DSL?

Ela foi criada justamente pra evitar o ReflectionUtil que existe em quase todos os projetos :)

eu já tinha visto...
é legal... fica muito mais limpo o código.

Mas por exemplo, este método

public static Field getPrimaryKeyField(Class<?> type) {

	for (Field f : type.getDeclaredFields()) {
	    if (f.isAnnotationPresent(Id.class)) {
		return f;
	    }
	}

	return null;
    }

pode ser reproduzido?

pois eu vi ali: [url]http://projetos.vidageek.net/mirror/annotations/reflecting/[/url]
eu pego as anotações, mas o que eu quero fazer é o inverso ... kkkk

Com o trugger você pode fazer o inverso assim:

import static org.atatec.trugger.element.Elements.element;

Element element = element().annotatedWith(Id.class).in(type);

Isso te retornará um elemento (encapsula o Field com os métodos de acesso e modificação) com a anotação Id.class. Se quiser o objeto Field pode usar a classe Reflection:

Field field = Reflection.reflect().field().annotatedWith(Id.class).in(type);
//ou
import static org.atatec.trugger.reflection.Reflection.field;

Field field = field().annotatedWith(Id.class).in(type);

Como não conheço o Mirror não sei te dizer como fazer isso nele.

D

vlw :smiley:

Criado 10 de novembro de 2012
Ultima resposta 10 de nov. de 2012
Respostas 11
Participantes 3