IG - Collecton declared by class, not interface

I like this inspection "Collection declared by class, not interface", but it would be 10X more useful if it was 100% accurate and offer a quickfix.

Currently I will see a warning like this:

"Declaration of HashMap should probably be weakened to 'Map'"

The warning is very wishy-washy because the inspection does not check to see
if any of the accessors of the variable are using methods declared only in the concrete class and not available in the superclass.

I realize doing all the checks could be expensive but this is exatly the kind
of work I want IDEA to do for me automatically.

Also, as far as I know there is no refactoring for me to automate changing the
type from HashMap to Map or Vector to List, etc. It would be great if there was
a quickfix available to automate this.

Here is a Related Jira:
IG: 'Declaration should probably be weakened' triggers incorrectly
http://www.jetbrains.net/jira/browse/IDEABKL-3233

6 comments

Indeed, that would be useful. +1 from me :)

0

Hello Alex,

Also, as far as I know there is no refactoring for me to automate
changing the type from HashMap to Map or Vector to List, etc. It
would be great if there was a quickfix available to automate this.


Although not in the form of QuickFixes, there are two plugins that can help:
-'Change Type Refactoring' by Tom
-'Refactor-J 2.0' by SRR ("Weaken Type")

Both will only show the interface type if there are no usages of the methods
of the concrete (implementing) type.

-tt


0

I tried out Thomas Singer's Change Type Refactoring and
SixthAndRedRiver's RefactorJ 2.0 plugin - Weaken Type
refactoring, and both of these have serious limitations.

They work fine if you have a simple case where you have a field
or local variable and all the methods invoked are part of the
interface class, e.g.

 v = new ArrayList(10);
    for (int i = 0; i < 10; i++) {
        v.add(i);
    }
  }
}
]]>


The biggest limitation I found was that they do not work if the
variable/field is passed to a method whose parameter type is
also that class rather than an interface, e.g. method(HashMap
map) isntead of method(Map map).

 l = new ArrayList(10);
        for (int i = 0; i < 10; i++) {
             l.add(i);
        }
        functionUsingArrayList(l);
    }

    private static void functionUsingArrayList(ArrayList l) {
        for (Integer i : l) {
            System.out.println(i);
        }
    }
}
]]>


A further problem is that when the refactoring runs into a
limitation, both plugins just popup a generic error message, so
there is no indication of what the problem was. The Change Type
Refactoring says "No alternatives found." SSR's Weaken Type says
"Cannot perform refactoring."

In real code, I find that if the developer wrote the code using
concrete types, e.g. HashMap instead of Map, ArrayList instead
of List, etc. then all the methods will also be parametized with
the concrete tyepes. So, these refacotring aren't that helpful.

SSR's Weaken Type already supports weakening the type of method
parameters, so it seems it could put it all together by starting
from the initial local variable/method parameter/ field variable,
and then attempt to also weaken the parameter type of the
methods passed that variable, and this may continue recursively.

This functionality should really be part of IDEA though, and not
in a plugin IMO.

0

This functionality should really be part of IDEA though, and not
in a plugin IMO.


+1

0

Hello Alex,

SSR's Weaken Type already supports weakening the type of method
parameters, so it seems it could put it all together by starting
from the initial local variable/method parameter/ field variable,
and then attempt to also weaken the parameter type of the
methods passed that variable, and this may continue recursively.
This functionality should really be part of IDEA though, and not in a
plugin IMO.


I must say that I totally agree. I use 'Weaken type' a lot. It's quite high
in my 'top 10' of refactorings, trailing only rename/move/introduce/inline.

Having this feature and some of the functionality of 'SmartIntroduce' would
greatly improve the out-of-the-box refactoring experience of Selena.

An additional improvement would be smart keyboard-based selection of the
desired type. Regular SpeedSearch (ActionSelectionAid#SPEEDSEARCH) would
be nice. Perhaps a CamelCase variation of SpeedSeach, optimized for selection
in a list of types?

-tt


0

On 2007-04-12 20:42:10 +0400, Taras Tielkes <taras.tielkes@gmail.com> said:

Hello Alex,

>> SSR's Weaken Type already supports weakening the type of method
>> parameters, so it seems it could put it all together by starting
>> from the initial local variable/method parameter/ field variable,
>> and then attempt to also weaken the parameter type of the
>> methods passed that variable, and this may continue recursively.
>> This functionality should really be part of IDEA though, and not in a
>> plugin IMO.


I must say that I totally agree. I use 'Weaken type' a lot. It's quite
high in my 'top 10' of refactorings, trailing only
rename/move/introduce/inline.

Having this feature and some of the functionality of 'SmartIntroduce'
would greatly improve the out-of-the-box refactoring experience of
Selena.

An additional improvement would be smart keyboard-based selection of
the desired type. Regular SpeedSearch (ActionSelectionAid#SPEEDSEARCH)
would be nice. Perhaps a CamelCase variation of SpeedSeach, optimized
for selection in a list of types?

-tt


Theoretically, existing Refactor | "Use interface where possible" does
exactly what you need. It just doesn't let you reduce the scope of the
refactoring thus applying ArrayList->List will take a huge time on
large codebases.

0

Please sign in to leave a comment.