Question

First, some environment: this is Oracle's 1.6.0_45 JDK, and IDEA 13.1.

I have stumbled upon a most bizarre compiler error:

public final class AsmFunnels
{
    private AsmFunnels()
    {
    }

    // ...

    public static void funnelFieldNode(final FieldNode node,
        final PrimitiveSink into)
    {
        FieldNodeFunnel.INSTANCE.funnel(node, into);
    }

    // ...

    @ParametersAreNonnullByDefault
    private enum FieldNodeFunnel
        implements Funnel<FieldNode>
    {
        INSTANCE
        {
            @Override
            public void funnel(final FieldNode from, final PrimitiveSink into)
            {
                into.putUnencodedChars(from.name)
                    .putUnencodedChars(from.desc)
                    .putUnencodedChars(from.signature);
            }
        }
    }

    //...

}

Funnel and PrimitiveSink are from Guava; as to FieldNode, it is from ASM 5.0.1 (org.objectweb.asm.tree.FieldNode).

Note that I use IDEA (13.1 if that matters at all). Now, at first, I had one method defined like this:

public static void funnelFieldNode(final FieldNode node,
    final PrimitiveSink into)
{
    FieldNodeFunnel.INSTANCE.funnel(node, into);
}

IDEA show no warnings... But the compiler is not happy:

Error:(53, 33) java: /home/fge/src/perso/parboiled1/grappa/src/main/java/org/parboiled/transform/process/AsmFunnels.java:53: cannot find symbol
symbol  : method funnel(org.objectweb.asm.tree.FieldNode,com.google.common.hash.PrimitiveSink)
location: class org.parboiled.transform.process.AsmFunnels.FieldNodeFunnel

Line 53 is this one:

    FieldNodeFunnel.INSTANCE.funnel(node, into);

That is most bizarre, I don't see why. And then I did this:

private static Funnel<FieldNode> fieldNodeFunnel()
{
    return FieldNodeFunnel.INSTANCE;
}

public static void funnelFieldNode(final FieldNode node,
    final PrimitiveSink into)
{
    fieldNodeFunnel().funnel(node, into);
}

And with this, it compiles!

What is happening here? Who is right? IDEA or javac?

EDIT

I tried this, and it compiles:

((Funnel<FieldNode>) FieldNodeFunnel.INSTANCE).funnel(node, into);

But why do I need the cast at all?

I also tried to use a "regular singleton" like this and it also works:

@ParametersAreNonnullByDefault
private static final class FieldNodeFunnel
    implements Funnel<FieldNode>
{
    private static final Funnel<FieldNode> INSTANCE
        = new FieldNodeFunnel();

    @Override
    public void funnel(final FieldNode from, final PrimitiveSink into)
    {
        into.putUnencodedChars(from.name)
            .putUnencodedChars(from.desc)
            .putUnencodedChars(from.signature);
    }
}
Was it helpful?

Solution

It seems like a duplicate item - Enum class member with interface cannot find methods internally.

There was probably a bug in JDK-6 - see:

  1. Inconsistent compilation results for enum implementing an interface https://bugs.openjdk.java.net/browse/JDK-7049773

  2. Incorrect method resolution for enum classes entered as source files https://bugs.openjdk.java.net/browse/JDK-6724345.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top