Java支持泛型类型和方法。为什么不通用字段?

时间:2014-07-27 17:32:01

标签: java generics

尽管Java没有泛型[@ runtime],但最近我还陷入了某种通用的地狱。

情况(已删除简化和无用的上下文):

有一个库A,它提供了一个接口IA。有一个库B,它提供了一个接口IB。这两个库都是第三方库,我完全无法控制它们。 (实际上,有两个以上,但不要让它过于复杂。)

我的公司开发了一种引擎,它既定义又大量使用IA / IB的对象。因为我们的引擎必须处理所有实现,所以我们不能简单地定义一些interface IAB implements IA, IB并让我们所有的类实现它。因此,为了实现编译时类型安全&amp;方法曝光,决定使用通用方法。因此,每当需要'IAB'时,我们就会有 <IAB extends IA & IB> void doThis(IAB someObjectWithBothAPIs)

事实上,这非常有效。但是,不可能像<IAB extends IA & IB> IAB fieldWithBothAPIs;那样简单(IA & IB fieldWithBothAPIs;)。这带来了我们的问题:

为什么不呢?

基本上,允许任意TypeParams(opt)的(设计级别?)原因是什么,而实例字段仅限于具体Type

JLS§8.3

FieldDeclaration:
    FieldModifiers(opt) Type VariableDeclarators ;

JLS§8.4

MethodDeclaration:
    MethodHeader MethodBody

MethodHeader:
    MethodModifiers(opt) TypeParameters(opt) Result MethodDeclarator Throws(opt)

2 个答案:

答案 0 :(得分:1)

泛型方法在运行时从其调用上下文接收其类型参数。它可以在不同的情况下接收不同的类型。

通用字段如何接收类型参数?根据在某些情况下的使用,该字段不能具有不同的类型。它必须具有单一类型,在编译时已知。

答案 1 :(得分:1)

你可以这样做,而不是在宣言中。

interface IA {}
interface IB {}
interface IC {}

class Generic<IAB extends IA & IB> {
    final IAB iab;

    Generic(IAB iab) {
        this.iab = iab;
    }

    <IBC extends IB & IC> void method(IBC arg) {
        IBC ibc = arg;
    }
}

避免在每一行上执行此操作的一个很好的理由是,扩展相同内容的两种类型可能不一样。

例如,你可以写的图像

 class Generic {
    <IAB extends IA & IB> IAB iab;
    <IBA extends IA & IB> IBA iba;

    <IAB extends IA & IB> void method(IAB arg) {
       iab = arg; // error, types are not the same.
       iba = iab; // compile error as the types are not the same.

与此相同,语法正确且无法编译。

 class Generic<IAB extends IA & IB, IBA extends IA & IB> {
    IAB iab;
    IBA iba;

    <IAB extends IA & IB> void method(IAB arg) {
       iab = arg; // error, types are not the same.
       iba = iab; // compile error as the types are not the same.