如何从另一个通用 class 参数转换通用参数?
How to cast Generic parameters from another generic class argument?
我想在传递特定类型的 T2 时将对象 T 转换为 T2。 T2 是来自接口 T 的 class,因此 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;
}
我在概念上有什么地方错了吗?
我该如何解决这个问题?
实际上,您不能从 as
调用编译器无法根据您对 T2
施加的约束在编译时确定的任何方法。
在你的问题中,T2
可以是任何扩展 Object
的东西,所以你只能调用其中声明的方法,如 toString
、hashCode
等......非常无用。
如果出于某种原因您可以缩小 T2
类型(因此 T
)以扩展更具体的 class 或接口,那么您将可以访问其成员方法,例如,假设 T(即 T2)保证为 Number
,因此您可以调用 intValue
.
这可能会解决你使用 T
方法的问题,例如 getSequence
因为我认为实际上 T
在你的代码中是有界的 class定义 getSequence
方法。假设它调用了 SequenceContainer
。
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;
}
完整的解决方案是使用 lambda,允许调用者提供需要在方法内部调用的 T2 代码。
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;
}
请注意,我借此机会将返回的 sorted-map 的值概括为第三种类型 X
...这可以简单地 T2
并将在编译时无缝解决时间取决于您提供的 lambda。现在你调用这个签名的方式假设 t2OwnMethod
returns ... 一个 String 是:
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);
现在,请注意第二个参数 (exampleSSC) 毫无用处...因此您可以简单地忽略它。
我们可以在这里走得更远,使用 Java 流来完成问题代码中的所有工作:
final SortedMap<Integer, String> result = myScs.stream()
.map(t -> (SpecialSequenceContainer) t)
.collect(SequenceContainer::getSequence,
SpecialSequenceContainer::t2OwnMethod,
(s1, s2) -> s1,
TreeMap::new);
请注意,(s1, s2) -> s1
lambda 仅在存在键冲突时才会被调用,也许永远不会出现这种情况,但无论如何您都需要提供值合并函数。
我想在传递特定类型的 T2 时将对象 T 转换为 T2。 T2 是来自接口 T 的 class,因此 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;
}
我在概念上有什么地方错了吗? 我该如何解决这个问题?
实际上,您不能从 as
调用编译器无法根据您对 T2
施加的约束在编译时确定的任何方法。
在你的问题中,T2
可以是任何扩展 Object
的东西,所以你只能调用其中声明的方法,如 toString
、hashCode
等......非常无用。
如果出于某种原因您可以缩小 T2
类型(因此 T
)以扩展更具体的 class 或接口,那么您将可以访问其成员方法,例如,假设 T(即 T2)保证为 Number
,因此您可以调用 intValue
.
这可能会解决你使用 T
方法的问题,例如 getSequence
因为我认为实际上 T
在你的代码中是有界的 class定义 getSequence
方法。假设它调用了 SequenceContainer
。
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;
}
完整的解决方案是使用 lambda,允许调用者提供需要在方法内部调用的 T2 代码。
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;
}
请注意,我借此机会将返回的 sorted-map 的值概括为第三种类型 X
...这可以简单地 T2
并将在编译时无缝解决时间取决于您提供的 lambda。现在你调用这个签名的方式假设 t2OwnMethod
returns ... 一个 String 是:
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);
现在,请注意第二个参数 (exampleSSC) 毫无用处...因此您可以简单地忽略它。
我们可以在这里走得更远,使用 Java 流来完成问题代码中的所有工作:
final SortedMap<Integer, String> result = myScs.stream()
.map(t -> (SpecialSequenceContainer) t)
.collect(SequenceContainer::getSequence,
SpecialSequenceContainer::t2OwnMethod,
(s1, s2) -> s1,
TreeMap::new);
请注意,(s1, s2) -> s1
lambda 仅在存在键冲突时才会被调用,也许永远不会出现这种情况,但无论如何您都需要提供值合并函数。