Generic Restriction Hell: Bound Mismatch

落花浮王杯 提交于 2019-12-04 07:21:46

You must be doing wrong something else as the following works fine:

import java.util.HashMap;

public class Q {
    class A {
    }
    class B {
    }
    class C extends B {
    }
    class D<T extends B> extends A {
    }

    class StringMap<T extends A> {
        HashMap<String, T> _elements;
    }

    class DC extends D<C> {

    }

    //and go to update X
    class X {
        StringMap<D<C>> thing1 = new StringMap<D<C>>(); // still works fine
        StringMap<DC> thing2 = new StringMap<DC>(); // NO error!!!
    }
}

Try to post such a class reproducing your error.

As mentioned, your code is OK, although if i can guess, you meant to write the following line, which will indeed cause an error:

StringMap<D<C>> _thing = new StringMap<DC>; //error

The reason is the same as that which causes the following to be a problem:

ArrayList<Number> = new ArrayList<Integer>();

The generic type parameter given to a class when defining an identifier's type, i.e. in the lvalue, cannot be instantiated, i.e. in the rvalue, by a type whose parameter inherits the parameter given in the lvalue. If the parameters are different, the types are not considered compatible, even though intuitively they should have been (if generics were implemented in the language a little differently).

It's a bit of a gotcha...

I'm not really sure why you want to do this and what you want to use the StringMap for exactly, but changing the StringMap definition to this will allow what you've done to compile:

class StringMap<T extends Undoable<? super T>> {
  HashMap<String, T> _elements;
}

Which means that the type T must be an Undoable of any type as long as that type is a contravariant of T (indeed T itself). So now you can do this:

StringMap<DC> _thing1 = new StringMap<DC>(); // no more error
_thing1._elements.put("a key", new DC());

Having said that, this is just a theoretical exercise - i would strongly recommend you avoid using such complex inheritance hierarchies, but its difficult to suggest an alternative without the full use case.

I hope that helps!

Hmmm. I hope this isn't ancient old, but I'm solving a problem I also had. I noticed that in D, D must extend B or C must extend D due to a loop-around in A., enough to make me put in a bunch of effort for no one to notice. The problem is in the StringMap class, which strictly wants its own input to extend a generic class whose generic must be its input.

D works because D is the same class mentioned within the extension. It's safe. D refers to itself. D extends A, String>. Making a StringMap with it is good because D implements Undoable> because D extends A, String>, which extends Undoable>. DC, on the other hand must also implement Undoable, which impossible due to it only extending D; a solution could be for it to also implement Undoable where a new definition of methods with DC is needed to work. This is the real problem you are encountering. I hope this solves your problem.

My old problem:

In class D, T extends B, but then D extends A>. However, instead of returning the expected A or A>, it extends A, String>. However, D doesn't extend B. Therefore, both A, String> and A. Since inheritance from two of the same interface with different generic enclosed classes is not implemented in Java, T must extend D. However, C does not extend D, which is the problem you are encountering which is a problem you might need to fix in the future.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!