In Java Spring Boot using IntelliJ, how do I refactor existing class usages to a different class? I don't want to rename an existing class, but migrate to a new class. For example, change Fruit to Automobile class,
This reference does not help, https://www.jetbrains.com/help/idea/rename-refactorings.html#rename_class_example
The problem, as you know, is that all usages of your class are linked to it in IntelliJ. You can solve this by relinking all the usages to the new class.
Say you have ClassA and ClassB. You want to move all usages of ClassA to use ClassB.
Step 1 - rename ClassA to ClassATemp. Make sure to not use Shift-F6 for this, i.e. don't use IntelliJ's refactoring rename. Just change the text. Do the same for the filename. Now you have successfully changed ClassA to ClassATemp, and your code is completely broken. Hurray!
Step 2 - rename ClassB to ClassA. During this step, links to ClassA will "re-establish", but with the new class. You may need to reimport everything to the new package, or alternatively change the package as well (might be more of a hassle).
Step 3 - re-rename the newly renamed ClassA back to ClassB. Make sure to do this using IntelliJ's refactor. All links will now follow.
Final step - re-rename ClassATemp to ClassA.
You can try to use "Type migration" refactoring, see this
On the toolbar:
Edit -> Find -> Replace in Files...
Related
We have some portion of functionality packed in an external library and it is attached to our project. That library can't be changed in any way. Amongst others there are two classes lying inside it: com.myorg.Grandpa and com.myorg.Dad that extends com.myorg.Grandpa. Also there are com.myorg.Grandson extending com.myorg.Dad and a few other classes outside of the library extending com.myorg.Grandpa.
I decompile com.myorg.Grandpa class and add a new method new_method() to it.
Then I try to use new_method() in com.myorg.Grandson but IDEA won't let me do it cause Grandson extends Dad which extends library's Grandpa which doesn't contain new_method().
I tried to delete Grandpa from library and surprisingly IDEA didn't say a word and successfully compiled a project despite of the fact that in the boundaries of a library Dad extends non existing class.
The question is how to force Dad to extend a new Grandpa without deleting the one inside a library?
You could
Add an abstract class between Dad and GrandSon: Extend Dad, and add your method in the sub class. Then derive GrandSon from that sub class.
Put an instance of Dad in a new class, and let your IDE create delegate methods to the aggregated Dad instance. Again add your new method to the new class.
There is another possibility:
If you have to modify classes in place, use aspectj to weave in code: aspectj changes the byte-code (it does not need source code) at run-time. This way you can add methods or fields.
The fact is that you are duplicating classes with full package signature, so you will get the one that the classloader loads first. I know that in Websphere you can tweak classloader priorities, but couldn't say in your case.
Anyway, why not just do it without decompiling? You are causing yourself hard coupling to an external library and bad practices (maybe copyright issues) by decompiling/customizing. Besides, if the library gets updated, you will run into trouble having to reconstruct your customized classes.
Options:
Create your own implementation, for instance:
Create an Interface that replicates all methods in Grandpa plus the one you need.
Extend Grandpa class and implement the added method from your interface, all other methods will be left intact.
Extend all other extending classes from your own class hierarchie.
Instead of using the libraries common class, use your Interface as naming
This way you are kind of creating your own interface to the library, if it changes, you know where to make changes.
You could even do it without the interface, it's kind of wrapping the functionality, it would depend on what you need to achieve.
Anyway, I would try to solve it by own code and not by messing up with the library, it is just not worth it to do such tricks, if a new Programmer takes the project, they will need a lot of time to find out why and how it behaves.
Now, there might be variations in how to structure the class hierarchie, but it would depend on the specific implementation you need, so you would have to post more detailed data on what the library is and what you're trying to add to it if you expect some more specific answer...
Regards
It has to appear first to the class loader.
IDEA should load your class first if is in your project. You may also try to create a separate library for your class and include it in your project.
See also: http://www.jetbrains.com/idea/webhelp/configuring-module-dependencies-and-libraries.html
I have created a new class out of an old class with different method implementations. Now, I want to update all the references of that old class to this new class. Is there anyway to do this automatically in eclipse?
I can actually do a rename(with update references) to this old class and copy the new code into this but the entire code being in source control makes my life a tougher with this process.
I am just wondering if there is an easy way to do this and have both classes at the end and have the references updated to the new class.
Using the refactoring functionality should do the trick. Refactor the old class into the new one:
Right click on the class name, Refactor > Rename > Put the new name of the class > Press Enter.
This should do it.
I don't know of any existing refactoring that does exactly that, but it's simple enough to:
Temporarily rename your new class to something else.
Do a refactor/rename of the old class to the new class name.
Manually (non-refactor) rename the old class back to its original name.
Manually (non-refactor) rename the new class back to its original name.
That way you get the power of the rename refactoring to help you update the references, but in the end, the classes are still the same as they were.
right click your class file select refactor then rename it what ever you want ..
My guess is that person asking the question is using something like Perforce or ClearCase where temporarily renaming files is a pain.
The best bet is to do a simple Eclipse global file search and replace.
Click on Search -> File
and click on the Replace button on the bottom.
I need to find the references to external method say Foo.getInstance() in specific type hierarchy, basically i want to restrict the search results to specific class and all subclasses, i am not interested in all references. Is it possible to do with eclipse or any custom plugin? Thanks
You can do this creating a working set with only the files holding your hierarchy.
Then CTRL+H and Java Search with scope "Working Set".
If the classes are all within a package you can select that in Project Explorer then perform Java Search with scope "Selected".
Working sets are awesome
I have identified a workaround. Requires viewing eclipse search results(in "show as list" mode).
For example ClassA has several subclasses (ClassB,C..Z) which inherits methodA defined on class A and calls them.
Perform method reference in eclipse and change the view to "show as list" using triangle/View menu appearing on top-right corner. This will list method signatures containing super-class/sub-class references so you can easily pick or drop from the search result.
If there are too many results to filter through you can Copy this onto file editor and use search keyword of subclass name (ClassB) and each line containing classB is a potential result which calls methodA on classB object.
Note: If method signature uses classA object reference and within body it type-casts to classB then you need to pick that entry and not drop it. I'd also recommend working set approach mentioned above. This is alternate approach to the question posted.
I am having trouble finding the correct refactor option for the following scenario:
I have code like this (in Outer.java):
public class Outer {
// ... class stuff
public static class Inner {
// ... inner class stuff
}
}
I am looking for a way to select Inner, and have it converted to a top level class, in it's own .java source file. I know this is pretty easy to do manually with copy/paste etc., but the inner class is referenced in a lot of places, and I would like the refactor option to handle the change everywhere it is referenced.
I have tried the option Refactor -> Extract Class... but that does something weird with a field called data that I don't quite understand.
Eclipse version is 3.5.1 Galileo.
How do I refactor a static inner class to be a top level class?
Edit: Can't believe I overlooked the option to do this. Thanks for all your correct answers, +1 to you all. I'll still need to accept an answer, so if there is any more useful info, e.g. gotchas with the script, there is still a purpose to leaving an answer.
This is so easy I can't believe I missed it:
With the cursor anywhere within the inner type, right click and select:
Refactor -> Convert Member Type to Top Level...
(There is no shortcut in the default settings)
This automatically extracts the inner type, and places it in it's own file, in the same package and directory as the outer type.
Update
In later versions of Eclipse this refactoring has been renamed "Move Type to New File"
For completeness, version 4.x of Eclipse has changed terminology and now they call that operation as Move Type to New File...
Extract Class is not what you want.
I just did this using Eclipse 3.4.2
Select Inner
Right click 'Refactor->Convert Member Type To Top Level...'
I have 3.4.1, and if I right-click on Inner, >refactor, I have the option "Covert member Type to top level..", which does exactly what you want.
Use Refactor -> Convert Member to Top Level Type
For Intellj2018.1.
right click in the inner class
Refactor
Move
Move to upper level
I often refactor code first by creating an inner class inside the class I'm working on--When I'm done, I move the entire thing into a new class file. This makes refactoring code into the new class extremely easy because A) I'm only dealing with a single file, and B) I don't create new files until I have a pretty good idea of the name/names (Sometimes it ends up as more than one class).
Is there any way Eclipse can help me with the final move? I should just be able to tell it what package I want the class in, it can figure out the filename from the class name and the directory from the package.
This seems like a trivial refactor and really obvious, but I can't figure out the keystrokes/gestures/whatever to make it happen. I've tried dragging, menus, context menus, and browsing through the keyboard shortcuts.
Anyone know this one?
[edit] These are already "Top Level" classes in this file, not inner classes, and "Move" doesn't seem to want to create a new class for me. This is the hard way that I usually do it--involves going out, creating an empty class, coming back and moving. I would like to do the whole thing in a single step.
I'm sorry I gave the wrong answer before. I rechecked, and it didn't do quite want you want. I did find a solution for you though, again, in 3.4.
Highlight the class, do a copy CTRL-C or cut CTRL-X, click on the package you want the class do go into, and do a paste, CTRL-V. Eclipse will auto generate the class for you.
Convert Member Type to Top Level doesn't quite work. Doing that will create a field of the outer class and generate a constructor that takes the outer class as a parameter.
In Eclipse 3.6, you can do: Refactor -> Move type to new file
Right-click the class name (in the source code) and choose Refactor -> Convert Member Type to Top Level. It doesn't let you choose the package, though.
For IntelliJ IDEA / Android Studio:
Refactor -> Move -> Move inner class MyInnerClass to upper level
Can be done in 2 refactorings :
Convert Member type to top level
Move