Java anonymous inner class calling enclosing type super types method

I give you an example to set some context here, so I have two interfaces each inheriting the same parent interface and defining their own implementation of the parent interface's abstract method.

interface A
{
    Set a();
}

interface B extends A
{
    @Override
    default Set a()
    {
        return null;
    }
}

interface C extends A
{
    @Override
    default Set a()
    {
        return null;
    }
}

In an interface called D, The implementation creates an anonymous inner class which then needs to call the super types (B and C) a() implementation.

interface D extends B, C
{
    @Override
    default Set a()
    {
        return new HashSet()
        {
            {
                final int totalSize = D.this.B.super.a().size() + D.this.C.super.a().size();
            }
        };
    }
}

The problem is that the expressions D.this.B.super.a() and D.this.C.super.a() do not get compiled successfully, so what is up ?

Thank you by the way for your efforts.

1 answer

  • answered 2018-10-11 19:38 rgettman

    Java allows you to access specific interface implementations with the syntax:

    InterfaceName.super.method()
    

    However, inside the anonymous class to get the enclosing instance with D.this. It is not allowed to combine these syntaxes to first get the enclosing instance, then its super-interface implementations.

    The solution here is to move the declaration of totalSize outside of the anonymous class so you can access the super-interface implementations. The anonymous class will still be able to refer to the local variable totalSize because it's final. (It would still be able to access it if it were effectively final -- not final but never reassigned.)

    final int totalSize = B.super.a().size() + C.super.a().size();
    return new HashSet()
    {
         // Anonymous class implementation here.
         // You can refer to totalSize.
    };
    

    You may have omitted the generics for brevity, but in case you didn't, you will want to include type parameters for Set and HashSet.