2017-05-09 10 views
2

プロジェクトでは、DTOとは別のオブジェクトを何度も作成する必要があります。私が直接汎用オブジェクトをインスタンス化することはできません、Java:デフォルトでないコンストラクタで汎用オブジェクトをインスタンス化します。

public class AssembleObjectFromDto<T,Tdto> { 
    public List<T> tFromDto(List<Tdto> tdtoList){ 
     List<T> tList = new ArrayList<>(); 
     for(Tdto tdto : tdtoList){ 
      tList.add(new T(tdto)); 
     } 
     return tList; 
    } 
} 

しかし:コードを繰り返していないの原則に従うことをしようと、私はこのような一般的なクラスを作成しようとしました。

私は、この問題を解決するために他にどのような方法を使用できるかを知りたかったのです。あなたは、コンパイラやランタイムでもないが、TとTdtoの具体的な種類を知ることができないので、それを行うことができないので、そのようなコンストラクタが存在する場合でも知ることができません。あらかじめ

+1

"しかし、私はgenをインスタンス化できませんエリックオブジェクトを直接。どうして? – AMB

答えて

4

感謝

しかし、あなたが渡すことができFunction<Tdto, T>代わりに:このメソッドは、一般的なクラスにする必要がないこと

List<Foo> dtos = assemble.tFromDto(fooDTOs, Foo::new) 

注:あなたは、次の方法を呼ぶだろう

public List<T> tFromDto(List<Tdto> tdtoList, Function<Tdto, T> constructor){ 
    List<T> tList = new ArrayList<>(); 
    for(Tdto tdto : tdtoList){ 
     tList.add(constructor.apply(tdto)); 
    } 
    return tList; 
} 

。それは一般的なことができ、静的な(とストリームを使用して単純化)することができます

public static <T, D> List<T> fromDTOs(List<D> dtoList, Function<D, T> constructor){ 
    return dtoList.stream().map(constructor).collect(Collectors.toList()); 
} 

この方法の単純さを考えると、あなたもそれを完全に削除することもできます。

+0

こんにちは、返信ありがとう、私はこのアプローチを実装しようとしていますが、私は "Foo :: new"のような表現で "新しいT(tdto)"部分を置き換えるのに問題があります – heisen

+0

あなたは本当ですか?この回答の最新版を読んでください(以前は間違いがありました)。あなたのFooクラスには、FooDTOを引数にしているpublicコンストラクタがありますか?詳細については、問題を再現した完全な例を投稿してください。 –

+0

はい、はいです。しかし、 "tList.add(constructor(tdto))"という行に "Method call expected"エラーが表示されています。 tFromDtoメソッドの – heisen

0

実際には、デフォルト以外のコンストラクタを使用して汎用オブジェクトをインスタンス化することは不可能であるとは限りません。

免責事項:これは特に反射に関連するため、これが最善のアプローチであるとは限りません。 JB Nizetが提案した簡略化された静的バージョンの使用を検討することもできます。しかし、これはちょうど最小のおもちゃの例であると仮定すると、私はOPsコードに基づいて元の質問に答えて、実際にはデフォルト以外のコンストラクタを使って一般的なオブジェクトを構築することが可能であることを示します。一般的なアセンブリクラスを使用

バージョン1、直接

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; 
    } 
} 

バージョン2、ジェネリック/テンプレートの特殊化を使用する:

は、実際の型を取得するためにtFromDto(List<Tdto>)と2つの抽象ゲッターをオーバーロードを定義AssembleObjectFromDto抽象クラスを作ることができtFromDto(Class<T>, Class<Tdto>, List<Tdto>) 1に最初の2つのClassの引数を渡す避けるためにジェンナリック引数TTdtoのいずれかを入力し、必要なすべてのタイプのクラスを特化します。これにより、より多くのクラスを犠牲にしてコードを読みやすくすることができます。また、専門分野はコード生成ツールで簡単に自動化する必要があります。

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: 1.

バージョンと比較して変わりません
関連する問題