Actually it is not true that it is impossible to instanciate a generic object with a non default constructor.
Disclaimer: I'm not saying this is the best approach, especially since it involves reflection. You might want to consider using the simplified static version suggested by JB Nizet. However assuming this is just a minimal working toy example I'll answer the original question based on the OPs code and show that it is indeed possible to construct generic objects with a non default constructor.
Version 1, Using the generic assembly class directly
AssembleObjectFromDto.java:
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.NoSuchMethodException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;
class AssembleObjectFromDto<T, Tdto>
{
public List<T> tFromDto(Class<T> clsT, Class<Tdto> clsTdto, List<Tdto> tdtoList)
throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException
{
List<T> tList = new ArrayList<>();
for(Tdto tdto : tdtoList)
tList.add(clsT.getConstructor(clsTdto).newInstance(tdto));
return tList;
}
public static void main(String[] args)
{
AssembleObjectFromDto<Obj, Dto> assembler = new AssembleObjectFromDto<>();
List<Dto> lstDto = Arrays.asList(new Dto(), new Dto(), new Dto(), new Dto());
try
{
List<Obj> lstObj = assembler.tFromDto(Obj.class, Dto.class, lstDto);
for(Obj o : lstObj)
System.out.println(o.getClass().getName());
}
catch(NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ex)
{
System.out.println(ex);
}
}
}
Dto.java:
class Dto {}
Obj.java:
class Obj
{
private Dto dto;
public Obj(Dto dto)
{
this.dto = dto;
}
}
Version 2, Using generic/template specialization:
To avoid passing the first two Class
arguments to tFromDto(Class<T>, Class<Tdto>, List<Tdto>)
one could make AssembleObjectFromDto
an abstract class defining an overload tFromDto(List<Tdto>)
and two abstract getters to retrieve the actual type of the gerneric arguments T
and Tdto
and then specialize the class for all required types. That should make the code a bit more readable at the cost of having more classes. Also the specialization should be easy to automate with code generation tools.
AssembleObjectFromDto.java:
import java.util.List;
import java.util.ArrayList;
import java.lang.NoSuchMethodException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
abstract class AssembleObjectFromDto<T, Tdto>
{
protected abstract Class<T> getProductClass();
protected abstract Class<Tdto> getAssemblerClass();
public List<T> tFromDto(List<Tdto> tdtoList)
throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException
{
return tFromDto(getProductClass(), getAssemblerClass(), tdtoList);
}
private List<T> tFromDto(Class<T> clsT, Class<Tdto> clsTdto, List<Tdto> tdtoList)
throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException
{
List<T> tList = new ArrayList<>();
for(Tdto tdto : tdtoList)
tList.add(clsT.getConstructor(clsTdto).newInstance(tdto));
return tList;
}
}
AssembleObjFromDto.java:
import java.util.List;
import java.util.Arrays;
import static java.lang.System.out;
import java.lang.NoSuchMethodException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
class AssembleObjFromDto extends AssembleObjectFromDto<Obj, Dto>
{
@Override
protected Class<Obj> getProductClass() { return Obj.class; }
@Override
protected Class<Dto> getAssemblerClass() { return Dto.class; }
public static void main(String[] args)
{
AssembleObjFromDto assembler = new AssembleObjFromDto();
List<Dto> lstDto = Arrays.asList(new Dto(), new Dto(), new Dto(), new Dto());
try
{
List<Obj> lstObj = assembler.tFromDto(lstDto);
for(Obj o : lstObj)
System.out.println(o.getClass().getName());
}
catch(NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ex)
{
System.out.println(ex);
}
}
}
Dto.java, Obj.java:
Remain unchanged compared to version 1.