JEP proposal: Improved variance for generic classes and interfaces

elias vasylenko eliasvasylenko at
Tue Oct 28 01:21:46 UTC 2014

Am I correct that to just have the bridge method call the 'overriding'
method would give the following behaviour?:

Bar bar;
Integer i;
// ...
bar.test(i); // false
((Foo) bar).test(i); // false
((Predicate) bar).test(i); // true

I can see why this is undesirable, but fwiw I'd be okay with it...
On 28 Oct 2014 00:19, "elias vasylenko" <eliasvasylenko at> wrote:

> Ah, good point. Covariance is still easy to have without any such fuss, so
> far as I can see, but having the one without the other is no good.
> I still think this at least bears further consideration. There could still
> be a solution in allowing contravariant overriding in this particular
> instance, i.e. having the user only need to implement test(Number) and
> having the bridge method just call that... since conceptually test(Integer)
> *should* have effectively been a bridge method *itself* to test(Number)
> anyway. If anything, it would be better this way regardless of the erasure
> issue imo, since it's just more strongly enforcing contravariance
> relationship encoded by the Predicate<? super T> syntax.
> There are still problems, since of course suddenly allowing contravariant
> overrides in one specific scenario creates situations which behave
> inconsistently with people's current expectations e.g.:
>     class Foo implements Predicate<Integer> {
>         public boolean test(Integer value) {return false;}
>     }
>     class Bar extends Foo implements Predicate<Number> {
>         public boolean test(Number value) {return true;}
>     }
>     foo.test((Integer) i); // returns true instead of false when invoked
> on an instance of Foo!
> Now that we have default methods we couldn't even just limit the feature
> to interfaces to avoid the problem.
> The only remotely tenable solution would be to force users to explicitly
> override test(Integer) with a method which does nothing but forward the
> invocation to test(Number). This would solve the erasure/bridge ambiguity,
> as well as the general ban on contravariant overrides, but still isn't
> ideal just because it feels a bit clunky... Syntax to explicitly mark a
> method as a 'forwarding' method without having to specify a body would
> help, but that is clearly outside the scope of this proposal, and a no-go
> unless it could be justified in and of itself as worth the added language
> complexity...
> Any thoughts? Have I talked myself out of this? Are there other problems
> I've missed in rambling on which make this moot, or does that about cover
> it?
> Cheers,
> Eli
> On 27 October 2014 23:03, Remi Forax <forax at> wrote:
>> On 10/27/2014 11:52 PM, Dan Smith wrote:
>>> On Oct 26, 2014, at 4:53 PM, elias vasylenko <eliasvasylenko at>
>>>> wrote:
>>>> Just a quick question/suggestion: it seems like a handy side-effect of
>>>> the proposed changes is the potential for relaxation of the limitation on
>>>> reimplementation of interfaces with different generic parametrisations, and
>>>> I'm wondering if you've considered this.
>>>> For example, it should be possible to allow something like this:
>>>>      class Foo implements Predicate<Integer> {}
>>>>      class Bar extends Foo implements Predicate<Number> {}
>>>> Since declaration-site variance guarantees compatibility of the
>>>> overriding parametrisation. Of course we can't technically override
>>>> test(Integer) with test(Number)... but from an outsiders perspective I
>>>> don't see this as incompatible with current language design philosophy...
>>>> At any rate, covariance should be more straightforward
>>>> I'm sure this would have come up if it hasn't already, but I couldn't
>>>> find any explicit mention of it.
>>> That's a good idea, and not something we've looked into yet.  Thanks for
>>> the suggestion.
>>> —Dan
>> The problem here is not a typing problem but an erasure problem, both
>> Predicate<Integer> and Predicate<Number> require to generate a bridge
>> method but both test(Integer) and test(Number) have the same erasure
>> test(Object). So it's not possible without full reification to implement
>> that bridge.
>> cheers,
>> Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the compiler-dev mailing list