如何从另一个泛型类参数中转换泛型参数?

时间:2017-06-12 15:41:49

标签: java generics generic-programming generic-list

我希望在传递特定类型的T2时将对象T转换为T2。 T2是来自接口T的类,因此可以存在T2的多个实现。 至于铸造,它发生得恰到好处。但我无法访问类型转换函数的功能。我做错了吗?

protected <T, T2> SortedMap<Integer, T2> noNameFunction(List<T> things, T2 ts) {
    SortedMap<Integer, Object> sortedMap = new TreeMap <> (  );
    for (T t: things) {
        T2 as = ( (T2) ts );
        sortedMap.put ( as.getSequence(), as.getFunctionsFromCastedIbjectA() );
    }
    return sortedMap;
}

我在概念上错了吗? 我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

实际上,您无法调用编译器无法根据您对as施加的约束在编译时确定的T2中的任何方法。

在您的问题中,T2可以是Object延伸的任何内容,因此您只能调用其中声明的方法,例如toStringhashCode等等......非常无用。

如果由于某种原因你可以缩小T2类型(因此T)以扩展更具体的类或接口,那么你将获得对其成员方法的访问权限。例如,想象一下T,因此T2保证为Number,因此您可以拨打intValue

这可能会解决T方法的问题,例如getSequence因为我认为实际上T在您的代码中被限定为某个定义{{1}的类} 方法。让我们说它叫getSequence

SequenceContainer

完整的解决方案是使用一个lambda,它允许调用者提供需要在方法中调用的T2代码。

protected <T extends SequenceContainer, T2 extends T>  SortedMap<Integer, T2> noNameFunction(List<T> things, T2 ts) {
    SortedMap<Integer, Object> sortedMap = new TreeMap <> (  );
    for (T t: things) {
        T2 as = ( (T2) t ); 
        sortedMap.put ( as.getSequence(), as.t2OwnMethod() ); // fail to compile, due to the call to t2OwnMethod.
    }
    return sortedMap;
}

请注意,我借此机会将返回的有序映射的值推广到第三种类型protected <T extends SequenceContainer, T2 extends T, X> SortedMap<Integer, X> noNameFunction(List<T> things, T2 ts, Function<T2, X> valueFunction) { SortedMap<Integer, Object> sortedMap = new TreeMap <> ( ); for (T t: things) { T2 as = ( (T2) t ); sortedMap.put ( as.getSequence(), valueFunction.apply(as)); // fail to compile, due to the call to t2OwnMethod. } return sortedMap; } ...这可能只是X并且将在编译时无缝地解决,具体取决于你提供什么lambda。现在,假设T2返回...一个字符串,则调用此签名的方式为:

t2OwnMethod

现在,注意第二个参数(exampleSSC)是没用的......所以你可以简单地省略它。

我们可以更进一步,使用Java流来完成问题代码中的所有工作:

List<? extends SequenceContainer> scs = ...;
SpecialSequenceContainer exampleSSC = ...; /// SpecialSequenceContainer extends 
SortedMap<Integer, String> option1 = noNameFunction(scs, exampleSSC, ssc -> ssc.t2OwnMethod());
// or 
SortedMap<Integer, String> option2 = noNameFunction(scs, exampleSSC, 
    SpecialSequenceContainer::t2OwnMethod);

请注意,final SortedMap<Integer, String> result = myScs.stream() .map(t -> (SpecialSequenceContainer) t) .collect(SequenceContainer::getSequence, SpecialSequenceContainer::t2OwnMethod, (s1, s2) -> s1, TreeMap::new); lambda仅在存在键冲突时才会被调用,也许情况永远不会如此,但无论如何都需要提供值合并功能。