2015-04-17 74 views
1

参考下面的代码片段,我有一个接口Splitter,其中接受通用类型参数TV。有一个实现是CompanySplitterImpl。可能有很多这样的实现。java中通用类型实现的返回类型应该是什么

public interface Splitter<T, V> { 
    V[] split(T arg); 
} 

public class CompanySplitterImpl 
implements Splitter<Company, Department> { 

    @Override 
    public Department[] split(Company comp) { 

     return comp.getDepartment(); 
    } 
} 

我想写返回基于在工厂方法传递的一个关键参数值不同的实现工厂方法。

// Factory method to return different Implementation of Splitter 
// (Is Splitter return type correct?) 
public static Splitter getSplitter(String key) { 

    return new CompanySplitterImpl(); // Is this correct? 
} 

我的问题是什么是返回不同实施Splitter<K, V>实例的正确方式?

// Client to call factory method... 
// Not sure what will be type argument for Splitter type 
Splitter<?> split = getSplitter("dummyKey"); 

在客户端,什么是Splitter类型的类型参数?

+1

你连接到使用'String'作为一个关键的想法?请注意'Splitter'是[原始类型](http://stackoverflow.com/q/2770321/2891664),可能不是一个好主意。你正在失去安全性。相关:[*“避免在具有多个值类型的地图中进行未经检查的赋值?”](http://stackoverflow.com/a/22468599/2891664) – Radiodef

+0

也应该尽量避免使用泛型类型的数组 - 使用'列表'而不是。原因很复杂,但基本上仿制药可以很容易地避免泛型的类型安全益处。 – yshavit

+0

'CompanySplitterImpl'是一个'Splitter ',就像您定义的一样。 – Bubletan

回答

5

Splitter是原始类型。你不应该使用原始类型。由于密钥(String)没有携带类型信息,因此无法从传递给getSplitter的参数中推断出类型参数。因此,避免原始类型的唯一方法是使返回类型为Splitter<?, ?>

这是丑陋和强制方法的调用者投:

​​

这样做的更好的方法是使用携带类型信息的密钥,通常的方式做到这一点是使用Class<T>对象。

public static <T, V> Splitter<T, V> getSplitter(Class<T> key1, Class<V> key2) { 

    if (key1 == Company.class && key2 == Department.class) 
     return (Splitter<T, V>) new CompanySplitterImpl(); 

    // more cases 
} 

然后调用者可以这样做:

Splitter<Company, Department> split = getSplitter(Company.class, Department.class); 
+0

是否可以通过从某个外部配置文件中读取关键信息(Company.class和Department.class)来动态传递它? – Vinit89