Search code examples
javagenericspolymorphismgeneric-programming

Java class inner generic bound obscures parent interface generic bound definition


I have the following class structure, where I have a compiler error on the definition of the ProxyFactoryclass:

Error:(32, 47) java: type argument com.company.Factory.ProxyUpdatable is not within bounds of type-variable T

The minute I replace the definition of ProxyUpdatable to simply hold an object and remove it's type parameter however, the code compiles fine.

Why does the type parameter of ProxyUpdatable have an effect on the bounds of it's factory implementation ProxyFactory? As far as I can tell, adding generic bounds to ProxyUpdatable doesn't change anything bout the interface it implements Updatable<ProxyUpdatable>

package com.company;

public abstract class Factory<T extends Factory.Updatable<T>> {

    public interface Updatable<T> {
        void copyFrom(T updated);
    }

    static class ConcreteUpdatable implements Updatable<ConcreteUpdatable> {
        @Override
        public void copyFrom(ConcreteUpdatable updated) {/* copyFrom implementation */}
    }

    static class ProxyUpdatable<T extends Updatable<T>> implements Updatable<ProxyUpdatable> {

        private final T implementation;

        ProxyUpdatable(T implementation) {
            this.implementation = implementation;
        }

        @Override
        public void copyFrom(ProxyUpdatable updated) {/* copyFrom implementation */}
    }

    static class ConcreteFactory extends Factory<ConcreteUpdatable> {
    }

    static class ProxyFactory extends Factory<ProxyUpdatable> {
    }
}

Solution

  • Stop using raw types!

    It seems like the act of using raw types creates this compiler error. ProxyUpdatable is generic, so add generic parameters when you want to use it.

    To fix this, change the declaration of ProxyUpdatable to:

    static class ProxyUpdatable<T extends Updatable<T>> implements Updatable<ProxyUpdatable<T>> {
    

    Note that it now implements Updatable<ProxyUpdatable<T>>

    And then you have to change the declaration of ProxyFactory as well. You can make it extend Factory<ProxyUpdatable<ConcreteUpdatable>> or make ProxyFactory generic as well:

    static class ProxyFactory<T extends Updatable<T>> extends Factory<ProxyUpdatable<T>> {