1

I am having a map of String and Object and I am getting this map from an external source, for a particular scenario, I am getting this object as

"ArrayList<LinkedHashMap<String, Double>>"

ArrayList<LinkedHashMap<String, Double>> targetDetailContainer = null;
Map<String, Object> confData = getConfData();
if (confData.containsKey("Target-Details")) {
    targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
            .get((Object) "Target-Details");
}

now at the last line where I am casting the Object to

"ArrayList<LinkedHashMap<String, Double>>"

I am getting a warning -

Type safety: Unchecked cast from Object to

"ArrayList<LinkedHashMap<String, Double>>"

I have tried to do type check before casting, something like this,

if (confData.containsKey("Target-Details")
    && confData.get((Object) "Target-Details") instanceof ArrayList<?>) {
targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
        .get((Object) "Target-Details");
}

But it didn't worked. Please suggest something, How I can get rid of this warning.

Sameer Rathoud
  • 133
  • 3
  • 8
  • Warnings will occur whenever compiler cannot ascertain type of Objects.By using @SuppressedWarnings ("unchecked"),you are telling compiler"I know what I am doing and I dont need your advice.So just shut up".the onus then lies completely on you – Kumar Abhinav Aug 26 '14 at 14:43
  • possible duplicate of [How to avoid unchecked cast warnings with Java Generics](http://stackoverflow.com/questions/9499908/how-to-avoid-unchecked-cast-warnings-with-java-generics) – Infinite Recursion Aug 27 '14 at 06:51

5 Answers5

3

I would suggest @SuppressedWarnings ("unchecked") annotation since you cannot do much about this warning. It's not very harmful, but because of type erasure and lack of type information at compile time (for generic types) you can't really do anything else.

Lucas
  • 3,181
  • 4
  • 26
  • 45
2

The warning will exist as part of compile type checking against casting Objects of super type to an Object of specific type.It is the way by which compiler is telling you.

"Hey,I cant assure whether the Object you are casting is an Object of ArrayList<LinkedHashMap<String, Double>> and when you treat this Object as this type,be prepared for RuntimeExceptions.So from now on ,you are on your own."

If you only want to rid of this exception and you are prepared for any RuntimeException which may occur,go ahead and mark it with @SuppressedWarning ("unchecked") .But I suggest you do some defensive mechansim and edit you code thus

    ArrayList<LinkedHashMap<String, Double>> targetDetailContainer = null;
    Map<String, Object> confData = getConfData();

    if (confData.containsKey("Target-Details")) {

        Object value = confData.get("Target-Details");
        if (value instanceof ArrayList<?>) {
            ArrayList temp = (ArrayList) value;
            for (Object vals : temp) {
                boolean flag = false;
                if (vals instanceof LinkedHashMap<?, ?>) {
                    LinkedHashMap<?, ?> map = (LinkedHashMap) vals;
                    for (Map.Entry entry : map.entrySet()) {
                        if (entry.getKey() instanceof String
                                && entry.getValue() instanceof Double) {
                            flag = true;
                        }

                        if (!flag) {
                            throw new RuntimeException(
                                    "Objects are of different types");
                        }

                    }

                }
                targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
                        .get((Object) "Target-Details");
            }

        }
    }

Since the checking is huge and compiler cannot ascertain it for you ,it will give you unchecked warnings

Kumar Abhinav
  • 6,565
  • 2
  • 24
  • 35
0

You can add the

@SuppressWarnings("unchecked")

before your method to suppress this warnings.

mcdikki
  • 109
  • 4
0

Store the return value of confData.get((Object) "Target-Details" in an object and then type check that object to remove the warning.

Since you called confData.get((Object) "Target-Details" twice, it considers them as two different objects, one which you type-checked, one which you didn't.

It should be like this:

Object temp = confData
    .get((Object) "Target-Details");


if (confData.containsKey("Target-Details")
&& temp instanceof ArrayList<?>) {
targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) temp;
}

The above code may have typos since I am typing through mobile app, but the concept is to use a temp object.

Suppressing warnings should be avoided as it is not advisable and negatively impacts code quality.

Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
  • That's true, but code JUST to get rid of warning that indicates Java's flaw is in my opinion not the best solution either. It should be also achieved using reflection but there is a question - why would anyone want to do that? – Lucas Aug 26 '14 at 14:23
  • The temp variable gets deleted outside the scope of the method. It isn't really Java's "fault", if you call getter method twice, how can compiler of any language know that the return value of the first getter invocation has been type-checked while doing the second getter invocation? This has nothing to do with Java generics or language design @Lucas. – Infinite Recursion Aug 26 '14 at 14:28
  • The `temp` variable does not eliminate the warning as it is still impossible to verify the type arguments in the cast. Reflection does not help here, as the information is simply not available at runtime. That’s why the warning tells the programmer that the type can not be checked. – Holger Aug 26 '14 at 14:33
  • Yes, actually even the type check of temp as mentioned in the above solution didn't worked for me. The intent of this question was to be safe from bad casting and exceptions, as the data is coming from an external source, so not having much control on the data – Sameer Rathoud Aug 27 '14 at 05:05
0

You can't do almost nothing since compile time checking complaining you about the casting from Object to ArrayList<LinkedHashMap<String, Double>>. Just put the annotation @SuppressWarnings("unchecked") before your method.

Giorgio
  • 1,073
  • 3
  • 15
  • 33