3

I'd like to do something like this:

private Class<? extends Enum<?> implements IMultiBlockEnum> typeEnum;

How would I do that? The "&" instead of "implements" doesn't work, but Eclipse doesn't give a proper explanation either.

Christopher Klinge

4 Answers4

5

You can only use & when declaring an inferred parameter type, like this:

<T extends Enum & IMultiBlockEnum> void x(T a) {}

Wildcard types may not specify a type intersection as an upper bound.

If you start wondering why it is so, consider what would be the return type of typeEnum.newInstance(). It would have to be both Enum<?> and IMultiBlockEnum at the same time.

For the relevant JLS quote please refer to this answer.

P.S. Another thing that makes little sense in your example is that you end up using two independent wildcards, but obviously want it to be captured as the same type.

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • Okay, so there is no way to achieve my intended goal? Or is there some kind of workaround? Would it somehow be possible to add values() and such to the interface instead? – Christopher Klinge Jul 06 '13 at 18:36
  • You could add name(), ordinal() etc... to IMultiBlockEnum. But not the static methods such as values(). – user949300 Jul 06 '13 at 18:39
  • But adding values() doesn't seem to work that way. Afaik values() is generated during compilation and is thus not visible to the IDE during coding. – Christopher Klinge Jul 06 '13 at 18:42
  • @ChristopherKlinge It is visible on a pure `enum` type. Naturally, it can't be visible on an `Enum`-typed variable. More importantly, since Java Generics are implemented by type erasure, it would be technically impossible to produce such a bytecode which could generically access a `static` method of any class. – Marko Topolnik Jul 06 '13 at 18:57
0

You can't extend Enum

Enum types are final by design.

nachokk
  • 14,363
  • 4
  • 24
  • 53
  • But isn't that how you pass an enum as a parameter? I don't want to extend the enum. I have an interface and I want to make sure, that the enums a function receives are implementing that interface. – Christopher Klinge Jul 06 '13 at 17:29
  • But `enum` can `implements` an interface. That's the case here. – Marko Topolnik Jul 06 '13 at 17:32
  • @nacchokk This is not true. `public enum MyEnum` will create a type that extends `Enum`. – pickypg Jul 06 '13 at 17:33
  • @nachokk Correct, you cannot have subclasses of `MyEnum` above, but the generic block that Christopher is referencing would allow _any_ `enum` so long as it implements the requested interface. This is a convenient way to type safely have unique keys without implementing equals (among a few other benefits). – pickypg Jul 06 '13 at 17:40
  • I think that he can require the interface, or require an enum, but not both. Don't see the advantage to requiring that the implementation be an enum. IMO, he should just use `private IMultiBlockEnum typeEnum;` – user949300 Jul 06 '13 at 17:44
  • @user949300 The reason is, you can't call `ordinal`, `name`, or any other `Enum` method on that variable. – Marko Topolnik Jul 06 '13 at 17:51
  • Until "they" add an IEnum interface with ordinal(), name(), etc., I think OP is stuck. You can't require that a variable be both a class and an unrelated interface. – user949300 Jul 06 '13 at 18:02
  • @user949300 OP doesn't require that: he wants that to be the upper bound of his `Class` type. But you are right in principle: the return value of `newInstance` would have to be two types at the same time. This is the reason why the feature doesn't exist in Java. – Marko Topolnik Jul 06 '13 at 18:05
0

You can create your own class using the original Enum as you like without extend it

surfealokesea
  • 4,971
  • 4
  • 28
  • 38
0

If you want to require that the implementation be a certain enum, but also implement an interface, you need to define your own enum "class" implementing the interface(s) , e.g.

public enum MyFancyEnum implements IMultiBlockEnum {
  A,B,C,D;

  // put code to implement IMultiBlockEnum here, e.g.
  public void doTheMultiBlockEnumStuff(String input) {
      ...
  }
}

and then declare your variable as a MyFancyEnum, e.g.

private MyFancyEnum typeEnum = MyFancyEnum.C;
user949300
  • 15,364
  • 7
  • 35
  • 66