1

[I vote to reopen this for the community. The question What are the reasons why Map.get(Object key) is not (fully) generic does indeed nail the root cause of the issue. But for me, Stack Overflow is about answering questions, accessing working sample code, and supporting specific instances of API usage -- not about creating a canon of unique root causes. I was not able to find the other post, perhaps due to its title. Enums were created to provide a safe alternative to named constants. This issue defeats that benefit -- without mention in the API and without a compiler warning. Why reduce the level of safety to below that of named constants? For enum users this question is useful -- it comes up as #1 on google.]

Is this supposed to compile? It does, even though I'm getting an enum member of a different type (EnumDelta) from an enumMap initialized with type EnumAlpha. I thought that as a generic type, EnumMap would guarantee type safety with respect to EnumAlpha.

    import java.util.EnumMap;

    class Enum {

            static enum EnumAlpha { ALPHA, BETA; }
            static enum EnumDelta { DELTA, EPSILON; }



            static EnumMap<EnumAlpha, String> enumMap = null;

            public static void main (String[] args) {

                    enumMap = new EnumMap<EnumAlpha, String>(EnumAlpha.class);
                    String string = "foo";

                    enumMap.put(EnumAlpha.ALPHA, string);

                    //why does this line compile?
                    System.out.println(enumMap.get(EnumDelta.DELTA)); 


            }


    }

Program outputs:

null

John
  • 741
  • 9
  • 18
  • @shmosel yeah that's it -- you'd think they'd mention this in all caps in the API description of get(). Looks like I can use containsKey() as a practical check -- if I can assume that the member should be present in the map. However, the assertion I just added is not being tripped. – John Jul 01 '16 at 02:36
  • You're asking a separate question now. And you probably need to enable assertions. – shmosel Jul 01 '16 at 02:51
  • Should i withdraw the question then and post a new one? – John Jul 01 '16 at 02:52
  • You are right, assertion worked. Thanks. – John Jul 01 '16 at 02:54
  • 3
    It's perfectly type-safe. It just defies your expectations. – Radiodef Jul 01 '16 at 03:07
  • @Radiodef What am I missing now? My program broke when the wrong enumeration member was used as an argument to an EnumMap instance, and there was no compiler error or XLint warning. Enumerations were added to Java 1.5 in order to get us beyond the practice of using named constants. [Java, the Complete Reference, 9th Edition, p. 253]. EnumMap is [recommended elsewhere here](http://stackoverflow.com/questions/1574580/is-it-bad-practice-to-use-an-enums-ordinal-value-to-index-an-array-in-java). What is the point of using enumerations if there is no such benefit? Am I missing the big picture? – John Jul 01 '16 at 15:02
  • 2
    @JohnMeyer what you're missing is that EnumMap implements Map. So everything that applies to Map also applies to EnumMap. Map.get() can't be fully generic, EnumMap is a Map, so EnumMap.get() can't be fully generic. – JB Nizet Jul 01 '16 at 15:51
  • Yeah exactly. EnumMap is a convenience to move things into collections, but has little to do with the goal of enumeration. I'd call it EnumObjectMap. – John Jul 01 '16 at 18:04
  • 1
    Did you get a `ClassCastException`? If not, then it's type-safe. – newacct Jul 01 '16 at 22:10
  • @newacct, not to labor a point, but, "In computer science, type safety is the extent to which a programming language discourages or prevents type errors." [-wikipedia](https://en.wikipedia.org/wiki/Type_safety). A method, such as get(), that uses Object as a parameter, encourages type errors. What definition or assumptions regarding type safety are you working with? – John Jul 12 '16 at 12:33
  • @JohnMeyer: And it uses `Object` because that's what the requirements of the `Map` API require, that it is useful for you to be able to pass it any reference type, because in general any objects can be equal. – newacct Jul 12 '16 at 18:29

1 Answers1

1

The answer is no, with respect to EnumMap.get(), due to the explanation in this linked post.

I was able to avert the hard-to-understand null pointer exception by adding this line:

     assert enumMap.containsKey(EnumDelta.EPSILON);
John
  • 741
  • 9
  • 18