Can eclipse convert/refactor a method to a class? - java

This seems like it should be fairly straight-forward, but I can't see anything obvious. What I basically want to do it to point at a method and refactor->extract class. This would take the method in question to a new class with that method as top level public API. The refactoring would also drag any required methods and variables along with it to the new class, deleting them from the old class if nothing else in the old class is using it.
This is a repetitive task I often encounter when refactoring legacy code. Anyway, I'm currently using Eclipse 3.0.2, but would still be interested in the answer if its available in a more recent version of eclipse. Thanks!

I don't think this kind of refactoring exists yet.
Bug 225716 has been log for that kind of feature (since early 2008).
Bug 312347 would also be a good implementation of such a refactoring.
"Create a new class and move the relevant fields and methods from the old class into the new class."
I mention a workaround in this SO answer.

In Eclipse 3.7.1 there is an option to move methods and fields out of a class. To do so:
Make sure the destination class exists (empty class is fine, just as long as it exists in the project).
In the source class, select the methods that you want to remove (the outline view works great for this), right click on the selection, and choose Move
Select the destination class in the drop down/Browse
Your members are now extracted. Fix any visibility issues (Source > Generate Getters and Setters is very useful for this) and you are all set.

This seems like it should be fairly
straight-forward...
Actually, Extract Class is one of the more difficult refactorings. Even in your simple example of moving a single method and its dependencies, there are possible complications:
If the moved method might be used in code you don't know about, you need to have a proxy method in the original class that will delegate to (call) the moved method. (If your application is self-contained or if you know all the clients of the moved method, then the refactoring code could update the calling code.)
If the moved method is part of an interface or if the moved method is inherited, then you will also need to have a "proxy method".
Your method may call a private method/field that some other method calls. You need to choose a class for the called member (maybe in the class that uses it the most). You will need to change access from "private" to something more general.
Depending on how much the original class and the extracted class need to know about each other, one or both may need to have fields initialized that point to the other.
Etc.
This is why I encourage everybody to vote for bug 312347 to get fixed.

Have you tried the Move feature of the Refactor group ? You can create a helper class and move there anything you want.

Related

Eclipse refactor to add superclass to type hierarchy

I've read the different options that are listed in the manual for refactoring here but I don't think what I want is there.
I have a project with many batch jobs which are classes that extend org.quartz.Job to which I of course I can't make changes. As I find myself writing a bunch of the same code in each job to do things specific to my system, it becomes apparent that I should have an abstract class that is the parent of all my batch jobs and does those system-specific tasks, let's call that org.mycompany.MySystemJob which will extend org.quartz.Job
I would've imagined that this refactoring would be readily available, where all the classes that are directly extending from class A are made to extend from a new class B which is created by the refactor and made to extend A.
I've considered "extract superclass" but this is actually a lot simpler, since the methods would be from a single source and the "extract superclass" refactor asks you to manually add all the "sibling" classes which in this case are all real siblings already.
I know I can find all such classes in the type hierarchy and then change a single line on each. It is not that hard, sure, but it seems to me that saving this kind of manual work is exactly what refactoring is supposed to be.
Anyway, maybe I am just missing what is there. I hope so. Thanks.
The trick is to create a class/interface with the same qualified name as the library class/interface which can not be changed. If this class/interface is moved or renamed, all references that originally related to the class/interface of the library are automatically updated to this newly created class/interface.
Consider also to use composition over inheritance instead.

How to modify or substitute private method in a java class

I have a class which behavior I would like to change. I need to replace private method with another realization. Common reflection techniques allow to modify private variable or to invoke private methods. But I find little information about replacing entire methods.
I presume that there are advanced techniques to do so. May be its impossible with standard java reflection but there are probably other tools to recompile byte code in runtime.
Modify & replace:
One option is to mask the class with a modified copy (modify code, recompile code, add modified classes to the classpath before patched classes), similar to the approach used here to inspect how a normally unavailable method works.
If you do not have sources to modify, you can "reverse" almost any .class file into more-or-less readable source code using decompilers. Notice that, depending on licensing, you may not have permission to do so and/or to redistribute your changes.
Patch via agent:
You can also patch the methods using the -javaagent:<jarpath>[=<options>] commant-line option. The "agent" is a jar that gets to modify loaded classes and alter their behaviour. More information here.
Mock:
If you have control over where the methods are called, you can replace the target instance with a stubbed version. Libraries such as Mockito make this very, very easy:
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
Even though Mockito does not support mocking private methods natively (mostly because it is considered bad manners to look at other classes' privates), using PowerMock allows you to do so (thanks, #talex).
You can't replace method in runtime (at least without hack into JVM). But you can replace whole class. There are several way to do it. For example you can use thing called "aspect".
But from my experience I can say that if you need to do this you have wrong turn somewhere in beginning of you way.
Maybe you better make one step back and look at whole picture
Instead of going for advanced techniques, there is a simple trick to achieve this.
If you class is part of an open-source jar, get source code of this class file from grepcode.com. Change the method that you want to change and compile it. And update your jar file/classpath with this updated class file.

java code template

I'm trying to make a code template that will generate tostring, constructor from field, and a default constructor.
I already looked at Useful Eclipse Java Code Templates and in http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.user/reference/ref-tostring-templates.htm but it was not what I was looking for.
I tried this plugin http://eclipse-jutils.sourceforge.net/ but I still need to manually select an option in the menu (and it doesn't have a "constructor from fields" option).
I need to generate these methods and constructors for more then 100 classes so this the best way i found coz eclipse dont give tool to do it for more then one class and for this one class that he give this tool i need to do it one by one the (generate tostring ,constructor from field and also default constructor)
i will love to some help or some advice on a way to create these methods for all my classes, automatically.
thanks in advance.
I don't know of a plugin that will do this for multiple classes.
I'd just do it manually, even though it'd take time.
You could also use reflection and a scripting language like Groovy/JRuby/etc. to create the constructors, and rely on something like Commons' ToStringBuilder to create a toString, or just use reflection again.
(One problem is if you don't want a property in the constructor or toString you need to have a mechanism to tell the generator as much.)
I have just used Practically Macros, within a few minutes of install from the market place, I could generate *constructors*, getters / setters, toString, hashcode and equals (basically chaining the standard eclipse commands) in a single command. Just what I was looking for and saved me loads of time. I can also see a lot more uses for it, well done to Earnst (the creator).

Refactoring tool in Eclipse

My need is pretty simple: I want to change a method call objClass1.method1() by a call objClass2.method2() in my whole Eclipse project. Unfortunately, I can't find a plugin able to do this. Can you help?
Edit:
To be more accurate, objClass1 is part of a third party library, so I need to change the method calls. I can't start at the method definition. When I right-click on a method1 call, I have no "rename" option in my "Refactor" menu.
I don't want to change or rename my methods. I want to exchange one call by another in my whole project.
An example of what needs to be done:
Before refactoring:
Injector injector=Guice.createInjector(new IContactModule());
After refactoring:
Injector injector=IContactInjectorSingleton.getInjector();
And this needs to be done a several points in my project.
What you ask for is no refactoring. A refactoring is defined as "a change that alters the code while not changing the behavior of the code". In this sense renaming a class or renaming a method is a refactoring (you change the code but the program does the same as before). But what you suggest does NOT preserve the behavior of the code so there will never be a "refactoring" for this.
Of course one might be able to write a plugin that is able to perform the text changes you want in a more or less safe way. But this will only work in very specific circumstances (what if your new method needs an argument the old one dons't need? What if there are more than one method with the same name but different parameters? ...). So I don't believe such a plugin exists, nor it makes much sense to develop such a plugin.
Just right click on the class/method name and choose Refactor > Rename.
EDIT:
To be more accurate, objClass1 is part of a third party library, so I need to change the method calls. I can't start at the method definition. When I right-click on a method1 call, I have no "rename" option in my "Refactor" menu.
Hence I would suggest you to simply make a replacement:
Search menu > File, type the old name, choose the context of the search ("Enclosing project"), click on Replace and type the new name.
EDIT2:
From the example you added to the question I think that a manual replacement, using the tool I just suggested, it's the best way. It's a complex issue, as #Arne pointed out, so it's better to make it in a controlled way. Moreover I doubt it is such a frequent operation to require a plugin to be built.
You could use the eclipse refactoring by selecting the methods name. Right click for context menu or Alt-Shift-R, in the Rename-Dialog a preview dialog is available which shows all suggested changes in one place.
First, move the body of objClass1.method1() into objClass2.method2(), and have method1 simply call method2. It may not be quite as "simple" as that, if for instance method1 uses fields of Class1 for instance, in which case you should probably include this as a parameter to the new method and perhaps use getters for the fields. If you can make the method static before doing this, it will be easier to avoid those kinds of problems. Anyway, make that transformation, so method1 is just calling method2. Now use the Inline Method refactoring to make method1 go away. You're done.

Strategies for reverse engineering project that uses Guice?

I have tried to understand dependency injection and not quite gotten it, except I have managed to pick up the understanding that it makes it hard to understand somebody else's code. :'(
Anyway, I'm not sure how to briefly describe my problem but I will try. I am currently the sole coder working on a Java project that's been worked on by dozens of loners over about six years. It makes heavy use of Google's Guice library. I'm supposed to take some existing code and implement it differently; specifically, use the existing methods for password authentication and, instead of applying it to each JMenuItem in a JMenu, apply it to the whole JMenu, so that if the wrong password or no password is entered, all JMenuItems are disabled. This doesn't happen if the password is wrong, leading me to believe the problem is in the if statement, which is a long string of dependencies in itself:
if (!ViewScanApp.getApplication().getHistoryManager().isAuthenticated())
I trace my way back through this, to find that the HistoryManager class is an interface, and there my path seems to die; there's no code there, and it doesn't make a reference to any other class. I have found the end of the path through random exploration of the 100-odd classes in the project, but I can't quite seem to connect them. I cannot find where the first class I can find on the other end of this stack, AccessManagerImpl, gets called.
I could use an explanation of dependency injection that might be applicable to this situation. Thank you so much!
Assuming there's no #ImplementedBy annotation on the HistoryManager interface, you'll need to examine the Guice Module that is responsible for binding this type.
In Eclipse, there is a command to look for occurrences of a class. I'll bet that Netbeans has something similar. Use it to look for occurrences of HistoryManager. At least one of these should occur in a class that implements com.google.inject.Module (or extends AbstractModule). You'll likely see something like
protected void configure() {
…
bind(HistoryManager.class).to(HistoryManagerImpl.class);
…
}
Or, if you like quick-and-dirty empiricism, you can throw in a println():
HistoryManager mgr = ViewScanApp.getApplication().getHistoryManager();
System.out.println("HistoryManager implementation: " + mgr.getClass());
if (!mgr.isAuthenticated())
…
However you locate it, HistoryManagerImpl class is where you'll want to pick up the trail.
I haven't used it, but the Guice graphing tool might be helpful too.
Fire up a debugger. It will walk you through the exact class that is implementing that interface (assuming you have the source code to it)
Whenever you have an interface definition in Eclipse which is injected with Guice, instead of using F3 to go to the defintion which you would do if it was a class, then use Ctrl-T to choose among the implementations of that interface.
If you have more than one to choose from, then you need the module bindings printed out so you know which one to pick. Unfortunately Eclipse doesn't understand injection yet.

Categories