2016-03-23 12 views
1

私は別のモデルにキャストする必要があるJCRノードのList<Node>を持っています。現時点では、モデルのそれぞれが独立した機能を持っている:Javaでリスト値のキャストを標準化する

public List<MetaModel> castNodesToMetaModel(List<Node> nodes) { 
    List<MetaModel> models = new ArrayList<MetaModel>(); 
    for (Node node : nodes) { 
     models.add(new MetaModel(node, this)); 
    } 
    return models; 
} 
protected List<ArticleModel> castNodesToArticleModel(List<Node> nodes) { 
    List<ArticleModel> models = new ArrayList<ArticleModel>(); 
    for (Node node : nodes) { 
     models.add(new ArticleModel(node, this)); 
    } 
    return models; 
} 

は私がTタイプを使用してこのキャスティングを標準化することができます方法はありますか?

protected <T> List<T> castNodes(T className, List<Node> nodes) { 
    ArrayList<T> list = new ArrayList<T>(); 

    for (Node node : nodes) { 
     list.add(new T(node, this)); // Cannot do: new T() 
    } 

    return list; 
} 

答えて

1

はい、可能ですが、署名はわずかに異なる必要があります。

import java.lang.reflect.Constructor; 

protected <T> List<T> castNodes(Class<T> clazz, List<Node>) { 
    List<T> list = new ArrayList<T>(); 
    try { 
     Constructor c = clazz.getConstructor(Node.class, getClass());   
     for (Node node : nodes) 
      list.add((T) c.newInstance(node, this)); 
    } catch (Exception e) { 
     // handle 
    } 
    return list; 
} 

あなたは本当に(あなたがより多くの特定の種類をキャッチする必要があります)一般Exceptionをキャッチしてはならないが、これはあなたのアイデアを提供します。

+0

コンストラクタはjava.lang.reflect.Constructorのインスタンスですか? – bashaus

+0

はい。申し訳ありませんが、関連する輸入品を追加する必要があります。 –

+0

@bashausはいそれは –

0

パラメータclassNameを使用して、メソッドに渡すClassオブジェクトのClass.new instance()メソッドを呼び出すことができます。

2

使用するJava 8のアプローチ:

public static <T> List<T> mapNodes(List<Node> nodes, Function<Node, T> mapFunction) { 
     return nodes.stream().map(mapFunction).collect(Collectors.toList()); 
    } 

このようにそれを呼び出す:あなたはJava 7で立ち往生している場合は

List<MetaModel> metaModels = mapNodes(nodeList, node -> new MetaModel(node, this)); 

List<ArticleModel> articleModels = mapNodes(nodeList, node -> new ArticleModel(node, this)); 

**** **** EDIT

私はリフレクションの代わりに良いオブジェクト指向のアプローチを提案します。そして、あなたはこのように使用

public static <T> List<T> convertNodes(List<Node> nodes, NodeConverter<T> converter) { 
    ArrayList<T> newNodes = new ArrayList<>(); 
    for (Node node : nodes) { 
     newNodes.add(converter.convert(node)); 
    } 
    return newNodes; 
} 

private static interface NodeConverter<T> { 

    public T convert(Node node); 
} 
public static class NodeConverterFactory { 

    public static final NodeConverter<MetaModel> metaModel(final Object thiz) { 
     return new NodeConverter<MetaModel>() { 
      @Override 
      public MetaModel convert(Node node) { 
       return new MetaModel(node, thiz); 
      } 
     }; 
    } 
    public static final NodeConverter<ArticleModel> articleModel(final Object thiz) { 
     return new NodeConverter<ArticleModel>() { 
      @Override 
      public ArticleModel convert(Node node) { 
       return new ArticleModel(node, thiz); 
      } 
     }; 
    } 
} 

List<MetaModel> metaModels = convertNodes(nodeList, NodeConverterFactory.metaModel(this)); 

List<ArticleModel> articleModels = convertNodes(nodeList, NodeConverterFactory.articleModel(this)); 

あなたがなりコンバータのすべての種類を実装しないことができるので、反射的なアプローチよりも、より詳細な、それは(、明確より柔軟ですが、このような1種類のコンストラクタが付いている)、安全な型を設定します。リフレクションアプローチは、使用されるコンストラクタ/メソッドが存在しない場合、実行時の問題につながる可能性があります。

+0

私はこのアプローチが気に入っていますが、私たちはJava 7に固執していると思います。 – bashaus

関連する問題