如何从另一个通用 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 的东西,所以你只能调用其中声明的方法,如 toStringhashCode 等......非常无用。

如果出于某种原因您可以缩小 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 仅在存在键冲突时才会被调用,也许永远不会出现这种情况,但无论如何您都需要提供值合并函数。