|
|
|
[
Permlink
| « Hide
]
Eugene Vigdorchik - 20 Feb 07 18:42
That would make the whole inspection useless for e.g. retrieving Objects.
That's why I suggest it maybe should be an option. Note that I'm suggesting that you tighten the rules a little to only warn if it's impossible for the call to ever succeed: if there is a possibility it might succeed, no warning should be emitted (or, as an option, also emit a warning in this case).
We have lots of code like this: public boolean accept(Map<Integer,String> map, Object key) { return map.containsKey(key); } On the other hand, I do want to see a big warning in this case: public boolean accept(Map<Integer,String> map, String key) { return map.containsKey(key); } Just one quick last point: consider the consistency of this code:
Integer i = Integer.valueOf (0); Object o = i; String s = "Test"; List<Integer> l = new ArrayList<Integer> (); // No warning - good if (o.equals (i)) { } if (i.equals (o)) { } // Warning "Suspicious call to List.contains()" - not good if (l.contains (o)) { } // Warning "equals between objects of inconvertible types" - good if (s.equals (i)) { } if (i.equals (s)) { } // Warning "Suspicious call to List.contains()" - good if (l.contains (s)) { } At least for your original example, it looks suspicious to me, unless IDEA can use
dataflow analysis to make sure that the variable n is only ever assigned to an Integer. Why do you not have Map<Number,String> or else if you want Map<Integer,String> Map<Integer,String> map = getMap(); Integer n = new Integer(3); if (map.containsKey(n)) { ... } I don't want to be warned when the code is "suspicious", just "wrong". Using an Object to retrieve from a map that takes Integer keys could be considered "suspicious" but for me it gives too many false positives to be useful. On the other hand, using a String to retrieve from a map that takes Integer keys is valid Java but is always going to be a bug.
This would render the inspection useless for the cases where either type parameter or argument of the method have interface type. I would still suggest you introduce the variable of concrete type, and the inspection for single-used local variable be patched to account for this case.
Eugene - good point about interface types, although I don't have that specific use case in my code. Maybe the inspection should always warn about this case
I can't really see a nice general solution to this. For example, you suggest transforming this public boolean accept(Map<Integer,String> map, Object key) { return map.containsKey(key); } into this public boolean accept(Map<Integer,String> map, Object key) { if (key instanceof Integer) // Whoops, I get an unnecessary cast warning here :-/ return map.containsKey((Integer) key); else return false; } public boolean accept (Map<Integer, String> map, Object key) { if (key instanceof Integer) { Integer ikey = (Integer) key; return map.containsKey (ikey); } else { return false; } } public boolean accept(Map<Class<Integer>,String> map, Class<?> key) { if (key instanceof Class<Integer>) return map.containsKey((Integer) key); else return false; } |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||