3

I don't have that much experience in Java compared to .NET. In .NET, enums are treated as thin wrappers over integers, so you can easily create an enum value that is unnamed. For example:

// C# code
public enum Colors { Red, Green, Blue }

Console.Writeline(Colors.Red + " " + Colors.Green + " " + Colors.Blue); // Red Green Blue

var unknown = (Colors)(-1);
Console.WriteLine(unknown); // -1

Is it possible to do the same thing in Java?

edit: This seems to be the case from the fact that this code won't compile:

// Java code
enum Colors { R, G, B }

static int f(Colors c) {
    switch (c) {
        case R: return 1;
        case G: return 2;
        case B: return 3;
    } // Compiler complains about a missing return statement
}
James Ko
  • 32,215
  • 30
  • 128
  • 239
  • 1
    I certainly hope not! That sounds like a terrible idea! – Joe C Sep 10 '17 at 18:15
  • @JoeC I agree, too. I'm a little pedantic, so in my .NET code I always have a `default:` case where I throw an exception every time I switch on an enum, even if I've taken care of all the defined values. I'm wondering whether I have to do the same thing for Java. – James Ko Sep 10 '17 at 18:18
  • Absolutely NOT. In Java enums are type-safe and you cannot express this concept at all. – Jim Garrison Sep 10 '17 at 18:22
  • @JimGarrison See the update I posted; why doesn't the code compile if I switched over all possible values, then? – James Ko Sep 10 '17 at 18:23
  • I don't think this is a duplicate of "what's the difference..." question, because this question asks specifically why the compiler requires a return when `switch` exhausts all options. Voting to re-open. – Sergey Kalinichenko Sep 10 '17 at 19:00
  • 1
    The code from the edit doesn't compile because the compiler defensively assumes that the Colors enum might be changed (extended) after creating the compiled class file that uses the enum. So a (while compiling) complete case list might turn incomplete when later running, if the Colors enum changed in between. – Ralf Kleberhoff Sep 10 '17 at 19:00
  • 1
    @RalfKleberhoff I see. Wouldn't the compiler be able to handle it if the enum and switch statement lived in the same jar, though? – James Ko Sep 11 '17 at 00:19
  • Living in the same jar doesn't mean anything to the compiler because creating the jar is done after the compilation (just zipping some .class files). So you should include a 'default' clause although you know it will never be reached in your current program. – Ralf Kleberhoff Sep 11 '17 at 07:27

1 Answers1

3

Java implements enums differently from C#: rather than making them a thin wrapper over ints, it makes them thin wrappers around objects, a compiler-aided improvement on the type-safe enum pattern.

Compiler ensures that it is not possible to create an instance of an enum that is not included in the type.

There are advantages and disadvantages to each approach. C# stays closer to C and C++ enums, which behave like collections of named numeric constants. This makes it possible to create [Flag] enumerations - something that would not be possible with Java enums.

On the other hand, Java enums are fully working objects, complete with methods of their own, and an ability to implement interfaces. Methods can be added to C# enums as extensions, but it is not possible to implement an interface.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you for your answer, it's very informative (I upvoted). Do you know why the code I posted in the edit won't compile, though? – James Ko Sep 10 '17 at 18:25
  • You need to add the case default like in: 'default: throw new IllegalArgumentException();' – Florian Sep 10 '17 at 18:27
  • @JamesKo I think this is a shortcoming of the compiler. The only other value that you can pass to `f()` is `null`, but if you did, there would be a crash in the `switch` statement. – Sergey Kalinichenko Sep 10 '17 at 18:38