-2

I have an interface defining the following method:

public <C extends RTSpan<V>, V extends Object> void onEffectSelected(Effect<V, C> effect, V value);

I'm calling this like this:

mListener.onEffectSelected(Effects.BOLD, true);

with Effects.BOLD being an Effect<Boolean,RTSpan<Boolean>> object.

I was under the impression that the compiler should make sure that the two Vs in the onEffectSelected are of the same type?

However if I write:

mListener.onEffectSelected(Effects.BOLD, 1);

It compiles without issues and of course throws a runtime exception.

What's wrong here? How can I make sure that the second parameter has an identical type to the one used in the first parameter?

EDIT

public class GenericsTest {
    interface RTSpan<V> {}
    static class BoldSpan implements RTSpan<Boolean> {}

    static class Effect<V extends Object, C extends RTSpan<V>> {}
    static class BoldEffect extends Effect<Boolean, BoldSpan> {}

    interface TheListener {
        public <C extends RTSpan<V>, V extends Object> void onEffectSelected(Effect<V, C> effect, V value);
    }

    static class Effects {
        public static final Effect BOLD = new BoldEffect();
    }

    public static void main(String[] args) {

        TheListener listener = new TheListener() {
            @Override
            public <C extends RTSpan<V>, V> void onEffectSelected(Effect<V, C> effect, V value) {}
        };

        listener.onEffectSelected(Effects.BOLD, Boolean.TRUE);
        listener.onEffectSelected(Effects.BOLD, 1);     // this compiles
        listener.onEffectSelected(new BoldEffect(), 1); // this doesn't compile
    }
}

The issue seems to be Effects.BOLD. If I replace it with a new BoldEffect() the compiler complains. Does anyone know why the static instantiation throws off the compiler?

Emanuel Moecklin
  • 28,488
  • 11
  • 69
  • 85
  • Could you post a full but minimal working example? – Tunaki Dec 14 '15 at 19:40
  • Not sure if that would help. I'm assuming a part answer to my question is that both parameters are checked independently and both are correct (meeting the V extends Object bounds) so I guess the question is more how to make sure that the compiler checks whether the two Vs are identical. – Emanuel Moecklin Dec 14 '15 at 19:48
  • I don't think you need the V extends Object, and that might be what's causing issues. Can you try public , V> void onEffectSelected(onEffectSelected(Effect effect, V value); – Kylar Dec 14 '15 at 19:51
  • 1
    I can't reproduce this. Please provide an MCVE. – Sotirios Delimanolis Dec 14 '15 at 19:56
  • 1
    I used my close vote, but here you are: http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it – Sotirios Delimanolis Dec 14 '15 at 20:16
  • Close vote because "does not appear to be about programming". Haven't laughed that much for a long time... And what does a question about "What is a raw type and why shouldn't we use it?" have to do with this? – Emanuel Moecklin Dec 14 '15 at 20:20
  • 1
    No, I voted to close as unreproducible (more specifically), now retracted. Your `BOLD` field is of the raw type `Effect`. That has the effect (no pun intended) of erasing all generics in the method you use it with. The link explains all this. – Sotirios Delimanolis Dec 14 '15 at 20:21

1 Answers1

0
public static final Effect BOLD = new BoldEffect();

This use of raw types essentially turns off type checking entirely anywhere BOLD is used. Turn it into Effect<Boolean, BoldSpan> and type checking will work properly.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413