2
private <K> Map<K, Object> createMap(final Class<K> keyClass) {
    final boolean isEnum = keyClass.isEnum();

    if(isEnum) {
                    // The following two lines throw warnings
        final Class<? extends Enum<?>> enumCls = (Class<? extends Enum<?>>)keyClass;
        final Map<K, Object> map = (Map<K, Object>)new EnumMap(enumCls);

        return map;
    }
    else{
        final Map<K, Object> map = new HashMap<K, Object>();
        return map;
    }
}

Warnings

found   : java.lang.Class<K>
required: java.lang.Class<? extends java.lang.Enum<?>>
        final Class<? extends Enum<?>> enumCls = (Class<? extends Enum<?>>)keyClass;
                                                                           ^
T.java:9: warning: [unchecked] unchecked call to EnumMap(java.lang.Class<K>) as a member of the raw type java.util.EnumMap
        final Map<K, Object> map = (Map<K, Object>)new EnumMap(enumCls);
                                                   ^
T.java:9: warning: [unchecked] unchecked cast                                   
found   : java.util.EnumMap                                                     
required: java.util.Map<K,java.lang.Object>                                     
        final Map<K, Object> map = (Map<K, Object>)new EnumMap(enumCls);
                                                   ^
3 warnings
RAY
  • 6,810
  • 6
  • 40
  • 67

3 Answers3

5

There are some checks the compiler cannot do and it will give you a warning. The only way to avoid these in this method is to add annotation before the method

@SuppressWarnings("unchecked")

Even the collections like ArrayList so not compile without warnings.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • @Peter. I did add @SuppressWarnings("unchecked"), but the second line still has a rawType warnings meaning I shouldn't use the EnumMap raw type. Now, @SuppressWarnings({ "unchecked", "rawtypes" }) looks pretty ugly. – RAY Apr 01 '11 at 08:13
  • @Surraj, it has been available since Java 5.0 ;) – Peter Lawrey Apr 01 '11 at 08:14
  • You should never use @SuppressWarnings as your first try at getting rid of warnings. Most warnings appear for a reason! Generics in Java make a promise - they are only checked at compile time, and the promise is that if there are no warnings when you compile, then they won't break at runtime. If you are suppressing warnings, that promise may no longer be intact! For this reason you have to be super-careful and be 100% sure it is safe to suppress them. – ZoFreX Apr 01 '11 at 08:15
  • @RAY, I agree, but you have to have some way to let the compiler know this code is fine. It cannot work it out for itself. For this reason, I ignore these warnings because it rarely tells me something useful. ;) – Peter Lawrey Apr 01 '11 at 08:16
  • I agree with @ZoRrex, that you shouldn't suppress them until you are *sure* the compile just doesn't understand what you are doing. I never suppress them. (I just ignore them once I know they are safe, but leave them there in case I change something incorrectly) ;) – Peter Lawrey Apr 01 '11 at 08:17
  • @ZoRrex, @Peter, so would you say in this instance, it's perfectly safe then? Thanks for your help. – RAY Apr 01 '11 at 08:20
  • @RAY, It is because you have checked the types at runtime, something the compiler doesn't understand. – Peter Lawrey Apr 01 '11 at 08:21
  • @Peter, my preference is to suppress warnings that I know for sure are safe. This way, warnings server their purpose as an indicator of potential problems to look into before release. – RAY Apr 01 '11 at 08:22
  • @Peter, I wonder if next-generation compilers will be smart enough to figure things like this out. – RAY Apr 01 '11 at 08:23
  • The compiler already is smart enough to figure things like this out if you do things "the Java way" in most cases. It's provable that no compiler could be smart enough to work it out in all cases. @RAY: What are you actually trying to solve here? There are quite a few red flags in your code. – ZoFreX Apr 01 '11 at 08:36
  • @ZoFrex Problem to solve: this is an apparently safe snippet code, and the compiler is giving me warnings. I was trying to figure out if there was a way to do what I want to do without the compiler "feeling unsure about it". What do you mean "red flags", please elaborate. – RAY Apr 04 '11 at 05:07
1

You should use "instanceof" to check type, the compiler is aware of that check and won't throw a warning on the first line if you do that.

The second line should be written like "new EnumMap<K, Object>(enumCls);".

ZoFreX
  • 8,812
  • 5
  • 31
  • 51
0

Well, there is at least a way to get the Class<? extends Enum<?>> without warning:

if (keyClass.isEnum()) {
  Enum<?> e = (Enum<?>)keyClass.getEnumConstants()[0];
  Class<? extends Enum<?>> enumCls = e.getDeclaringClass();
  // snip
}

Still, as has already been said, there is no way to use K as type parameter for EnumMap. Hence suppressing the warning (after evaluating the risks) is perfectly fine.

sfussenegger
  • 35,575
  • 15
  • 95
  • 119