jeudi 22 mai 2014

Création d'une méthode de modèle virtuel en Java - Stack Overflow


The situation I'm trying to create is the following:


I have a base class containing a static template method that receives a ResultSet filled by a query in the database, and returns a list with the proper results.


I have some classes, that derive from the one cited above, that represents each table from the database and all of them have a constructor that receives the ResultSet and builds the object.


The code I've written is:


public class TableBase 
{
public static <T extends TableBase> List<T> getResults(ResultSet p_Rs) throws SQLException, InstantiationException, IllegalAccessException
{
List<T> v_Table = new ArrayList<T>();
T v_TB = null;
while(p_Rs.next())
v_Table.add(new T(p_Rs));
return v_Table;
}
}

The error I got is: Cannot instantiate the type T.


It is clear to me that it would be necessary for the compiler to "know" that all the child classes would implement the constructor that receives the ResultSet variable, but I can't create a "abstract constructor".


Does anyone have a clue on how to solve that?


Thank you all in advance.




You can not instantiate generic Types.


You can use either Factory


 public static <T extends TableBase> List<T> getResults
(ResultSet p_Rs, Factory<T> factory)

//Create instance using factory

Or Class as type.


public static <T extends TableBase> List<T> getResults
(ResultSet p_Rs, Class<T> type)
//type.newInstance()



You can't do that. You must tell the runtime exactly type.


Maybe you can do like this:



  1. TableBase must have a default constructor.

  2. TableBase must have a setResultSet method.

    public class TableBase {
    public static <T extends TableBase> List<T> getResults(ResultSet p_Rs, Class<T> clazz)
    throws SQLException, InstantiationException, IllegalAccessException {
    List<T> v_Table = new ArrayList<T>();
    T v_TB = clazz.newInstance();
    while (p_Rs.next())
    v_TB.setResultSet(p_Rs);
    v_Table.add(v_TB);
    return v_Table;
    }
    }




You can use reflect, something like:


while(p_Rs.next())
v_Table.add(newInstance(T, p_Rs));


public <T extends TableBase> T newInstance(T t, ResultSet p_Rs){
try {
Constructor constructor = t.getClass().getDeclaredConstructor(ResultSet.class);
return (T)constructor.newInstance(p_Rs);

} catch (Exception e) {
throw new RuntimeException();
}

}


The situation I'm trying to create is the following:


I have a base class containing a static template method that receives a ResultSet filled by a query in the database, and returns a list with the proper results.


I have some classes, that derive from the one cited above, that represents each table from the database and all of them have a constructor that receives the ResultSet and builds the object.


The code I've written is:


public class TableBase 
{
public static <T extends TableBase> List<T> getResults(ResultSet p_Rs) throws SQLException, InstantiationException, IllegalAccessException
{
List<T> v_Table = new ArrayList<T>();
T v_TB = null;
while(p_Rs.next())
v_Table.add(new T(p_Rs));
return v_Table;
}
}

The error I got is: Cannot instantiate the type T.


It is clear to me that it would be necessary for the compiler to "know" that all the child classes would implement the constructor that receives the ResultSet variable, but I can't create a "abstract constructor".


Does anyone have a clue on how to solve that?


Thank you all in advance.



You can not instantiate generic Types.


You can use either Factory


 public static <T extends TableBase> List<T> getResults
(ResultSet p_Rs, Factory<T> factory)

//Create instance using factory

Or Class as type.


public static <T extends TableBase> List<T> getResults
(ResultSet p_Rs, Class<T> type)
//type.newInstance()


You can't do that. You must tell the runtime exactly type.


Maybe you can do like this:



  1. TableBase must have a default constructor.

  2. TableBase must have a setResultSet method.

    public class TableBase {
    public static <T extends TableBase> List<T> getResults(ResultSet p_Rs, Class<T> clazz)
    throws SQLException, InstantiationException, IllegalAccessException {
    List<T> v_Table = new ArrayList<T>();
    T v_TB = clazz.newInstance();
    while (p_Rs.next())
    v_TB.setResultSet(p_Rs);
    v_Table.add(v_TB);
    return v_Table;
    }
    }



You can use reflect, something like:


while(p_Rs.next())
v_Table.add(newInstance(T, p_Rs));


public <T extends TableBase> T newInstance(T t, ResultSet p_Rs){
try {
Constructor constructor = t.getClass().getDeclaredConstructor(ResultSet.class);
return (T)constructor.newInstance(p_Rs);

} catch (Exception e) {
throw new RuntimeException();
}

}

0 commentaires:

Enregistrer un commentaire