java – Android getDeclaredFields value

Question:

I'm doing some android studies, I don't know much about the subject because I'm starting now, I'd like to create a simple CRUD mvc, where I want to call model.save() ;

So I created the following structure:

MainActivity.java

Produto produto1 = new Produto(this);
produto1.setId(1);
produto1.setNome("CELULAR");
produto1.setPreco(5.5);
produto1.Save();

Produto.java

@DatabaseTable (tableName = "produtos") 
public class Produto extends BaseModel{

     @DatabaseField(columnName="id",    columnType="INTEGER", primaryKey=true)
     private int id;

     @DatabaseField(columnName="nome", columnType="VARCHAR")
     private String nome;

     @DatabaseField(columnName="preco", columnType="DOUBLE", columnSize="10,9")
     private Double preco;

     @DatabaseField(columnName="endereco", columnType="TEXT", columnSize="50", canBeNull=true, defaultValue="NULL", unique=true)
     private Double endereco;

     public int getId() {return id;}
     public void setId(int id) {this.id = id;}
     public String getNome() {return nome;}
     public void setNome(String nome) {this.nome = nome;}
     public Double getPreco() {return preco;}
     public void setPreco(Double preco) {this.preco = preco;}

     public Produto(Context context) {
         super(context);
     }  
}

DatabaseTable.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) //can use in method only.
public @interface DatabaseTable {
    String tableName();  
}

DatabaseField.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) //can use in method only.
public @interface DatabaseField {
     String columnName() default "";  
     String columnType(); 
     String defaultValue() default "";
     String columnSize() default "";
     boolean canBeNull() default true; 
     boolean unique() default false; 
     boolean primaryKey() default false; 
     boolean autoIncrement() default false; 
}

BaseModel.java

public class BaseModel extends DBFactory<BaseModel> {
 public BaseModel(Context context) {
      super(context);
 }
}

DBFactory.java

public class DBFactory<T> extends SQLiteOpenHelper {
    private static final String DB_NAME = "VendasDB";
    private static final int DATABASE_VERSION  = 1;
    private final Context myContext;
    private static DBFactory mInstance = null;
    private static SQLiteDatabase myWritableDb;

    private Class t;
    public void set(Class t) { this.t = t; }
    public Class get() { return t; }

    public DBFactory(Context pContext){         
        super(pContext, DB_NAME, null, DATABASE_VERSION);
        this.myContext = pContext;
        this.set((Class) this.getClass());    
        Log.v("CreateTableOnModel",CreateTableOnModel());
    }

    public String Save()
    {
        Log.v("DBFactory", "SAVE()");
        Class clazz = get();

        DatabaseTable annot = (DatabaseTable) clazz.getAnnotation(DatabaseTable.class);
        StringBuilder sb = new StringBuilder();

        if(!annot.tableName().equals(""))
        {
            Field[] fields = clazz.getDeclaredFields();
            Field idField = null;

            try {
               idField = clazz.getDeclaredField("id");      
               idField.setAccessible(true);
               Object b = idField.get(get().newInstance());
               Log.v("idField:", b.toString());
            } catch (Exception nsfe) {
               System.out.println(nsfe.toString());
            }


        }
    }
}

Mistake:

03-31 16:26:23.780: I/System.out(32048): java.lang.InstantiationException: can't instantiate class br.com.rlsystem.vendas.model.Produto; no empty constructor

Answer:

The error occurs because you are trying to create an instance without passing arguments in the constructor of a class ( Produto ) that has parameters:

public Produto(Context context) {
    super(context);
}  

There are two ways to solve the problem:

  1. Remove the constructor with arguments and set the dependency on a setter .

  2. Retrieve a reference to the constructor and use the constructor 's newInstance passing in the necessary arguments.


Update

The get() method of the Field class needs an object instance to retrieve the attribute's value.

The problem in this case is that you are creating another empty object.

As Produto extends DBFactory indirectly, what you need is to refer to the object itself, in this case:

Object b = idField.get(this);
Scroll to Top