【问题标题】:Checked cast of parametrized generic abstract class to it's implementation检查参数化通用抽象类对其实现的强制转换
【发布时间】:2017-08-08 17:08:54
【问题描述】:

我有一个复杂的方法,它返回DiffResult<T, V> 的不同实现。我想对实现进行检查转换,以便调用它的方法并断言结果。

// this is ok
DiffResult<MockVersion, String> result = calculator.diff(a, b);

// this is problem
NewCurrentVersionDiffResult<MockVersion, String> newCurrentVersionDiffResult = assertDiffType(result, NewCurrentVersionDiffResult.class);

// this is ok
Assert.assertEquals("expected", newCurrentVersionDiffResult.getNewValue());

NewCurrentVersionDiffResult 具有以下标头

public class NewCurrentVersionDiffResult<T extends ProductDataVersion<T>, V> extends DiffResult<T, V>
{ /* ... */ }

我试过了

private static <D extends DiffResult<T, V>, T extends ProductDataVersion<T>, V> D assertDiffType(final DiffResult<T, V> result, final Class<D> type)
{
    Assert.assertThat(result, CoreMatchers.instanceOf(type));
    return type.cast(result);
}

这在执行时有效,但会报告编译警告

[WARNING] VersionDiffCalculatorTest.java:[34,102] unchecked method invocation: method assertDiffType in class VersionDiffCalculatorTest is applied to given types
  required: DiffResult<T,V>,java.lang.Class<D>
  found: DiffResult<VersionDiffCalculatorTest.MockVersion,java.lang.String>,java.lang.Class<NewCurrentVersionDiffResult>
[WARNING] VersionDiffCalculatorTest.java:[34,102] unchecked conversion
  required: NewCurrentVersionDiffResult<VersionDiffCalculatorTest.MockVersion,java.lang.String>
  found:    NewCurrentVersionDiffResult

我希望它能够正常工作并且没有警告。

我知道@SuppressWarnings("unchecked"),我自己在其他地方使用它。但是这种情况显然是被打破的,因为当我告诉 IDEA 从 assertDiffType(result, NewCurrentVersionDiffResult.class) 声明局部变量时,它会生成

NewCurrentVersionDiffResult newCurrentVersionDiffResult =

而不是

NewCurrentVersionDiffResult<MockVersion, String> newCurrentVersionDiffResult = 

警告还针对assertDiffType() 方法的调用,而不是针对方法本身。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    您将NewCurrentVersionDiffResult.class 传递给Class&lt;D&gt; 参数的方法,这是它如何确定D 的类型,这也是返回类型。请注意那里的NewCurrentVersionDiffResult 缺少通用参数。这就是该方法返回原始类型的原因。

    不幸的是,你不能只做NewCurrentVersionDiffResult&lt;MockVersion, String&gt;.class。如何处理这个is answered here的问题;长话短说,你应该使用Guava library中的TypeToken

    @SuppressWarnings("unchecked")
    private static <D extends DiffResult<T, V>, T extends ProductDataVersion<T>, V> D assertDiffType(final DiffResult<T, V> result, final TypeToken<D> type) {
        Assert.assertThat(result, CoreMatchers.instanceOf(type.getRawType()));
        return (D) result;
    }
    

    有了这个,你可以做到:

    NewCurrentVersionDiffResult<MockVersion, String> newCurrentVersionDiffResult = assertDiffType(result,
            new TypeToken<NewCurrentVersionDiffResult<MockVersion, String>>() {});
    

    【讨论】:

      【解决方案2】:

      使用所需类型的最佳方法,但您可以使用此 @SuppressWarnings("unchecked") 来抑制警告,在少数情况下我们不能做太多事情,如果不可能,我们必须使用 @SuppressWarnings("unchecked")

      【讨论】:

      • 谢谢,但这不是问题的解决方案,我已经更新了问题。
      猜你喜欢
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多