我希望在传递特定类型的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;
}
我在概念上错了吗? 我该如何解决这个问题?
答案 0 :(得分:3)
实际上,您无法调用编译器无法根据您对as
施加的约束在编译时确定的T2
中的任何方法。
在您的问题中,T2
可以是Object
延伸的任何内容,因此您只能调用其中声明的方法,例如toString
,hashCode
等等......非常无用。
如果由于某种原因你可以缩小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仅在存在键冲突时才会被调用,也许情况永远不会如此,但无论如何都需要提供值合并功能。