Problems with cast in Reflection

Asked

Viewed 64 times

-1

Good afternoon. I’m new to using the java Reflection API. I’m having the following problem, when trying to create a generic Dao class to be used in a CRUD for sqlite on android, I can’t cast a field for the corresponding type in the object class passed as input parameter. Follows the code:

public class DaoGenerico<E>{

    private E entrada;
    private Class classe;
    private SQLiteDatabase db;
    private List<Field> campos;
    private List<Method> metodos;
    private String banco;

    public DaoGenerico(E entrada, SQLiteDatabase db) {

        iniciaComponetes(entrada, db);

        if(!classe.isAnnotationPresent(TabelaNoBanco.class)) {
            throw new RuntimeException("Classe não pode ser persistida!");
        }

        TabelaNoBanco anotacao = (TabelaNoBanco) classe.getAnnotation(TabelaNoBanco.class);
        this.banco = anotacao.nomeTabela();

    }


    public boolean inserir() throws IllegalAccessException {
        try {
            ContentValues values = new ContentValues();

            for (Field f : campos) {
                f.setAccessible(true);
                Class<?> type = f.getType();

                /*Linha onde deve ser efetuado o cast, porem apresenta erro em type*/
                values.put(f.getName(), (type) f.get(entrada));

            }
            db.insert(banco, null, values);
            db.close();
            return true;
        }catch(ClassCastException e){
            throw new RuntimeException("Campo não pode ser convertido");
        } catch (Exception e){
            throw new RuntimeException("Não foi possivel inserir  objeto no banco de dados!");
        }
    }

    private List<Field> obterCampos(){
        return Arrays.asList(classe.getFields());
    }

    private List<Method> obterMetodos(){
        return Arrays.asList(classe.getDeclaredMethods());
    }

    private void iniciaComponetes(E entrada, SQLiteDatabase db) {
        this.entrada = entrada;
        this.db = db;
        this.classe = entrada.getClass();
        this.campos = obterCampos();
        this.metodos = obterMetodos();
    }
}
  • Puts the exact text of the error in the question

  • No error the android studio itself underlines red as error

1 answer

1


First that line:

private Class classe;

Could be:

private Class<? extends E> classe;

Then we see that your method inserir closes the object db, but it was not he who opened it. As good practice, usually the responsibility to close is of the one who opened it. What if the method inserir always returns true, then what would be the purpose of the type of return?

Your problem occurs in these lines:

                Class<?> type = f.getType();

                /*Linha onde deve ser efetuado o cast, porem apresenta erro em type*/
                values.put(f.getName(), (type) f.get(entrada));

What’s wrong? It is that to cast you must use open-parentheses + class-name + close-parentheses. It happens that type is not class name, but variable name. Therefore, the compiler does not recognize the cast and gives compilation error.

So how to do it? It can be with this horrible thing:

Object obj = f.get(entrada);
if (obj == null) {
    values.putNull(f.getName());
} else if (obj instanceof String) {
    values.put(f.getName(), (String) obj);
} else if (obj instanceof Boolean) {
    values.put(f.getName(), (Boolean) obj);
} else if (obj instanceof Byte) {
    values.put(f.getName(), (Byte) obj);
} else if (obj instanceof Short) {
    values.put(f.getName(), (Short) obj);
} else if (obj instanceof Integer) {
    values.put(f.getName(), (Integer) obj);
} else if (obj instanceof Long) {
    values.put(f.getName(), (Long) obj);
} else if (obj instanceof Float) {
    values.put(f.getName(), (Float) obj);
} else if (obj instanceof Double) {
    values.put(f.getName(), (Double) obj);
} else if (obj instanceof Short) {
    values.put(f.getName(), (Short) obj);
} else if (obj instanceof byte[]) {
    values.put(f.getName(), (byte[]) obj);
} else {
    throw new ClassCastException("Campo não pode ser convertido.");
}

Or if you want to use Reflection here too:

Object obj = f.get(entrada);
if (obj == null) {
    values.putNull(f.getName());
} else {
    Method m;
    try {
        m = ContentValues.class.getMethod("put", String.class, obj.getClass());
        m.invoke(values, f.getName(), obj);
    } catch (NoSuchMethodException e) {
        throw new ClassCastException("Campo não pode ser convertido.", e);
    } catch (InvocationTargetException e) {
        throw new AssertionError(e.getCause());
    }
}

Ah, and don’t forget to use campo.setAccessible(true) and metodo.setAccessible(true) where relevant. Otherwise, you may take a IllegalAccessException.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.