Nested classes, eg. anonymous classes, are often more convenient than creating separate classes, especially when working with something like the Command pattern or event listeners. For example:
JButton button = new JButton(); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // ... Do something useful } });
But there comes a point when the nested class becomes so bulky that code becomes unreadable. And sometimes you want to reuse the same class in another place – something that’s difficult with anonymous inner classes.
The answer would be to change the nested class into a top level public class (or a first-class citizen, if you like) that exists in its own file (eg. SomethingUsefulActionListener.java). But doing this manually can take a lot of time and is error-prone.
Eclipse has a couple of refactorings and quick fixes that help to make the job a lot easier. Converting an anonymous inner class to a top level class requires two refactorings only and will take you a couple of seconds instead of minutes. A (named) inner class takes only one refactoring. And passing arguments to the new class is also easy if you use some of Eclipse’s Quick Fixes.
Convert the anonymous inner class into a top level
Converting an anonymous inner class into a top level class takes 2 main refactorings: Convert it to a nested class and then convert the nested class to a top level class. If you have a nested class (ie. a named inner class), then just start at step 4.
Here are the instructions, but there’s also a video below with a quick example.
1. Convert the anonymous inner class to a nested class by standing on the anonymous class’ constructor and choosing Refactor > Convert Anonymous Class to Nested… (or Alt-T, O). A dialog prompting for the nested class details will appear.
2. Enter a name for the new nested class, select public as the visibility and deselect Declare the nested type as final.
3. Click Ok. Eclipse will create a new nested class inside the enclosing class and leave the constructor call where the anonymous class used to be declared.
4. Now convert the nested class into a top level class by standing on the class name and choosing Refactor > Convert Member Type to Top Level… (or Alt-T, V). A dialog prompting for the enclosing instance name will appear.
5. (Optional) If you want to access the enclosing class within your new class, then enter a name for the field that will be assigned to the class. I normally leave this blank.
6. Click Ok. Eclipse will create the new class (UsefulAction.java) and move it to a new file in the same package.
Here’s a quick video to show you how easy this is. In the example, we’ll convert an anonymous inner ActionListener class to a class called UsefulAction.java.
Passing arguments from the enclosing class into the new class
What about when the nested class accesses fields in the enclosing class? How do you easily get private fields from the enclosing class into the new top level class?
There isn’t a one-shot way to do this, but there are techniques to make it go a bit faster. One trick is via the following steps:
- First make sure you’ve created a named nested class (steps 1-3).
- Copy and paste the relevant private fields of the enclosing class into the nested class.
- Automatically generate a constructor for the nested class based on the fields you just copied (Alt+Shift+S, O).
- Navigate to the constructor error (Ctrl+.) where the nested class is instantiated and add the fields to the constructor.
The easiest way to see how this works is to watch the following video. In the example, I’ll pass the fields name and address to the new class.
Related Tips
- Instantly show a class/file in the Package/Project Explorer in Eclipse
- Generate class constructors in Eclipse based on fields or superclass constructors
- Navigate and fix errors and warnings in a class with Eclipse keyboard shortcuts
- Extract constants from strings and numbers with Eclipse refactorings
- Add, remove and reorder a method’s arguments instantly across multiple classes in Eclipse
- Some more tips on refactoring faster and using quick fixes more effectively.