37
votes

If I have a constant BAR in Foo, which I will use in a class C I'll have to write

Object o = Foo.BAR + "...";

which I can use Ctrl-Shift-M in Eclipse (with the cursor on BAR) to create a static import for like:

import static Foo.BAR;

Object o = BAR + "....";

I am current updating legacy code with literaly thousands of these I'd like to convert to static imports. Ctrl-Shift-O / Organize imports does not do it. Is there a trick I've missed?


EDIT: Actually, what I would prefer is a way to tell Eclipse that I want to have Ctrl-Shift-M do its magic on ALL instances in this particular class instead of just the single instance I have the cursor placed at. (It is legacy code so this actually IMPROVES readability :) )


EDIT: I've found that IntelliJ suggest doing this.

9
+1 For simply mentioning Ctrl-Shift-MRobert Munteanu
BTW: For those stumbling over here: ctrl-shift-m works for exactly this, place cursor on BAR, press it and you have your static import (tested in eclipse luna) even better described here: codeaffine.com/2012/03/28/how-do-you-import-static-in-eclipseDudelilama

9 Answers

10
votes

One cautionary note: excessive use of static imports can actually make your code less readable (imho), particularly if the constant name doesn't clearly indicate the class or enum from which it belongs. You can also get constant names from different classes/enums that sound similar or even have the same name.

So what you're forcing the reader to do is hope his IDE will tell him the class (via, say, a tool tip) or they have to navigate to it to find out what it is. Printouts and code snippets become that much less reeadable.

Honestly I use static imports extremely rarely for these reasons.

3
votes

I don't know any other automated refactorings to do what you're looking for, but there are two key aspects to doing this - one is adding the imports and the other is removing the class name from the constants.

For adding the imports, I recommend pasting import static application.KeyHolder.*; after the package on every file which uses them.

For removing the class name, in eclipse do a Java search for KeyHolder.* and search for a field. You can then do a find/replace for "KeyHolder." and replace with "". In order to prevent mismatches make sure the replaced item count is equal to the number of matches for that file. Also, make sure you search down and start after the imports.

2
votes

Regular expression was invented to solve problems like these! =)

you will need to write a small script (or use the IDE regex search/replace). The only problem is that if there are lots of classes that needs to be statically imported, then its just as much work. Otherwise, if its just one class like FOO.BLAH, then you can use a regex like

(\bFOO\.(\w+)\b) -> replace with group 2 ($2 or \2 or however your regex searcher does capture replaces).

you can try it here : http://www.gskinner.com/RegExr/ . Select the replace tab and type in $2

A problem might arise if you have expressions like this though: FOO f = FOO.blah + "FOO.blah" , so watch out for that.

As for the import statement at the top of the file, eclipse has an auto import feature where it does autoimport on format, and it works as long as the name of the import is unique enough. Or, if you cant use it because the name is too common, you can just use a perl script to do the regex instead, and prepend the static imports.

1
votes

Eclipse can do a global search and replace with regular expression over all files in the project.

To add the static import at the beginning of all files you could replace the package declaration by itself plus the static import.

Then do a project wide organize imports, and you're all set.

Be careful, though, this could also make a big mess if you do it wrong.

1
votes

Sounds like a nice idea, but after you have changed all the files, how much better will they be? Perhaps you should think about only changing the files which you are working on for other reasons already.

0
votes

If I were faced with such a challenge, I'd probably write a small program to do it for me. Ruby and Python (JRuby and Jython?) are pretty well suited for the task, although you could do it in Java too.

OK, so that'll probably take you at least the same amout of time as doing it by hand, but at least you'll be having fun :).

-1
votes

Well something which pops in as a solution. I would recommend using a simple groovy script. Basically the semantics are related to parsing the import statements and the files they refer to. Some basic steps could be like

  1. Recurse each file inside directory.Check whether the file extension is .java
  2. Match any line which starts with import
  3. For each such line open the relevant source file(you already know the path from the import statement).
  4. Match the field/method declaration for a static modifier using reflection
  5. Add static after the import statement for matches found in step 5.

If i get some time i will try and post a small groovy script for doing the same.

-2
votes

Make sure no conflicts with other constant classes

replace all the "Foo." with empty (" ")

use this line at the top. worked for me

import static Foo.*

-3
votes

I don't know if it would fit your needs, but you can always have these constants defined in an interface and have all your classes just implement this interface. Then using some smart RegExp as others suggest you could get rid of all Foo. occurences.

Example:

public interface Foo {
   static final String constant1 = "Some";
   static final String constant2 = "Value";
   //...
}

And then

public class YourClass implements Foo {
   public YourClass() {
      System.out.println("Hello " + constant1);
   }
}