Эту статью можно рассматривать как краткий обзор c gif-ками по рефакторингам Java-файлов в IDEA для начинающих.
Осторожно, много тяжелых gif-картинок.

«Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” —M. Fowler (1999)
Содержание
— Edit Property Value (без примера)
— — Type Parameter (без примера)
— — Subquery as CTE (без примера)
— Find and Replace Code Duplicate
— Use Interface Where Possible
— Replace Inheritance with Delegation
— Replace Constructor with Factory Method
— Replace Constructor with Builder
— Lombok и Delombok (без примера)
— Internationalize Список источников
Введение
Цель данной статьи — показать доступные способы рефакторинга для Java-файлов (многие способы будут работать и для других языков). Как использовать эти приемы в реальной жизни показано в замечательном видео Тагира Валеева (ссылка в списке источников).
Думаю, каждый, кто работает в IDEA, знает, что в ней куча способов для рефакторинга кода. И почти уверен, что каждый второй смотрит анонсы новой версии, где красиво показаны новые способы рефакторинга и заглядывал в раздел Refaсtor:

Но не уверен, что все точно знают что и как делают все элементы этого списка, хотя они все детально описаны в справки к idea
В статье представлены фрагменты кода, порядок действий и анимации почти для каждого пункта. Также постарался добавить, где возможно, ссылку на замечательную книгу Refactoring: Improving the Design of Existing Code (Martin Fowler). Чтобы не сильно раздувать трафик пришлось довольно сильно обрезать много gif-картинок, поэтому обязательно смотрите использованный код под катом. Горячие клавиши приведены для Windows/LInux по умолчанию.
Раздел «Refaсtor»
Пойдем сверху вниз по порядку.
Пункт «Refactor This» (Ctrl+Alt+Shift+T)
Данный пункт используется для быстрого доступа к списку доступных способов рефакторинга. Заметьте, список зависит от места, где вы его вызываете. Здесь и далее в коде указывает на место каретки в коде, при вызове.


Пункт «Rename» (Shift+F6)
Позволяет переименовать практически любой идентификатор в коде, будь то переменная или названия класса. Изменения распространяются по всему проекту, в некоторых случаях, включая и комментарии. (У Фаулера переименованию посвящено 2 главы — “Rename Field” и “Rename Variable”)

Использованный код
До
public class Main { public static void main(String[] args) { System.out.print("Hello"); invo<caret/>ke(", World"); } private static void invoke(String text) { //text System.out.println(text); } }
После
public class Main { public static void main(String[] args) { System.out.print("Hello"); newFunctionName(", World"); } private static void newFunctionName(String text) { //text System.out.println(text); } }
-
Переименование переменной

Использованный код
До
public class Main { public static void main(String[] args) { System.out.print("Hello"); invoke(", World"); } private static void invoke(String te<caret>xt) { //text System.out.println(text); } }
После
public class Main { public static void main(String[] args) { System.out.print("Hello"); invoke(", World"); } private static void invoke(String newText) { //newText System.out.println(newText); } }
-
Переименование вложенного класса

Использованный код
До
public class Main { public static void main(String[] args) { System.out.print("Hello"); invoke(", World"); } private static void invoke(String text) { //text System.out.println(text); throw new MyExc<caret>eption(); } public static class MyException extends RuntimeException { } }
После
public class Main { public static void main(String[] args) { System.out.print("Hello"); invoke(", World"); } private static void invoke(String text) { //text System.out.println(text); throw new NewMyException (); } public static class NewMyException extends RuntimeException { } }
-
Переименование класса

Использованный код
До
public class Main { public static void main(String[] args) { MyS<caret>ervice service = new MyService(); service.service(); } }
После
public class Main { public static void main(String[] args) { NewMyService myService = new NewMyService (); myService.service(); } }
-
Переименование пакета

Использованный код
package gen<caret>eral; public class Main { public static void main(String[] args) { NewMyService service = new NewMyService(); service.service(); } }
После
package org.test.java.src; public class Main { public static void main(String[] args) { NewMyService service = new NewMyService(); service.service(); } }
Пункт «Rename File»
Переименовывает файл и ссылки на этот файл. В принципе можно вызывать через Shift+F6 если выделен файл. В диалоговом окне можно указать область поиска для переименований (Scope), искать ли ссылки или в комментариях и строчках

Использованный код
До
public class Main { public static void main(String[] args) throws IOException { Path path = Paths.get("src/general/TestFile.txt"); String read = Files.readAllLines(path).get(0); System.out.println(read); } }
После
public class Main { public static void main(String[] args) throws IOException { Path path = Paths.get("src/general/TestFile2.txt"); String read = Files.readAllLines(path).get(0); System.out.println(read); } }
Пункт «Change Signature» (Ctrl+F6)
У Фаулера этому посвящена глава “Change Function Declaration”. В новой версии IDEA «Change Signature» был немного доработан. Я знаю два пути:
-
первый путь — прямой — изменить сигнатуру метода и вызвать обновление,
-
второй — через диалоговое окно.
Пример для первого способа (через изменения сигнатуры метода)
Изменяем сигнатуру метода. В этот момент слева появляется «R» и в контекстном меню появляется пункт «Update usages to reflect signature change», который позволяет обновить все использования метода.

Использованный код
До
public class ChangeSignature { public static void main(String[] args) { invokeMethod("Hello"); invokeMethod("World"); } private static void invokeMethod(String text) { System.out.println(text); } }
После
public class ChangeSignature { public static void main(String[] args) { invokeMethod("Hello", null); invokeMethod("World", null); } private static void invokeMethod(String text, String newType) { System.out.println(text); } }
Пример для второго способа (через диалоговое окно)
В диалоговом окне можно изменить состав переменных, exception, и даже сгенерировать переопределенный метод.

Использованный код
До
public class ChangeSignature { public static void main(String[] args) { invokeMethod("Hello"); invokeMethod("World"); } private static void invokeMethod(String<caret> text) { System.out.println(text); } }
После
public class ChangeSignature { public static void main(String[] args) { invokeMethod("Hello"); invokeMethod("World"); } private static void invokeMethod(String text) { invokeMethod(text, null); } private static void invokeMethod(String text, String newName) { System.out.println(text); } }
Пункт «Edit Property Value» (Alt + F6)
На данный момент (Idea 2020.2) экспериментальная функция и по умолчанию не включена. Включить можно параметром property.value.inplace.editing=true Поэтому примеры не привожу.
Пункт «Type Migration» (Ctrl + Shift + F6)
Позволяет изменить тип переменной, включая сигнатуры методов, возвращаемый тип переменной.

Использованный код
До
public class ChangeSignature { public static void main(String[] args) { Inte<caret>ger hello = 1; print(hello); } private static void print(Integer text) { System.out.println(text); } }
После
public class ChangeSignature { public static void main(String[] args) { Number hello = 1; print(hello); } private static void print(Number text) { System.out.println(text); } }
Пункт «Make Static» (Ctrl + Shift + F6)
Позволяет сконвертировать метод или внутренний класс в статический. (Противоположность Convert To Instance Method)

Использованный код
До
public class MakeStatic { public static void main(String[] args) { MakeStatic makeStatic = new MakeStatic(); makeStatic.sayHello(); } public void say<caret>Hello() { System.out.println("Hello, World"); } }
После
public class MakeStatic { public static void main(String[] args) { MakeStatic makeStatic = new MakeStatic(); MakeStatic.sayHello(); } public static void sayHello() { System.out.println("Hello, World"); } }
Пункт «Convert To Instance Method»
Позволяет сконвертировать статический метод в нестатический (противоположность ”Make Static”). При этом можно указать к какому классу будет относится новый метод.

Использованный код
До
public class MakeStatic { public static void main(String[] args) { sayHello(); } public static void sa<caret>yHello() { System.out.println("Hello, World"); } }
После
public class MakeStatic { public static void main(String[] args) { new MakeStatic().sayHello(); } public void sayHello() { System.out.println("Hello, World"); } }
Пункт «Move Classes» (F6)
В принципе делает, что и написано, перемещает классы.

Использованный код
До
package org.example.test.service; public class TestService { <caret> }
После
package org.example.test; public class TestService { }
Пункт «Copy Classes» (F5)
Многие программисты любят копировать файлы, а не начинать с чистого листа. Для этого прекрасно подходит F5. Меняем название на нужноe, указываем пакет и готово.

Пункт «Safe Delete» (Alt+Delete)
По функциональности почти повторяет то, что можно получить через контекстное меню (Alt + Enter), но позволяет удалять чуть больше. Поэтому, я заметил, у многих знакомых любимый способ рефакторинга — F2(следующая ошибка) и Alt + Enter или Alt + Delete. Можно удалять классы, переменные, методы. Перед удалением IDEA выполнит поиск использования удаляемых элементов, и если IDEA найдет, что они где-то используется покажет диалоговое окно Usages Detected. Про удаление неиспользуемого кода у Фаулера есть целая глава — “Remove Dead Code”

Использованный код
До
package org.example.test; public class MainClass { public static void main(String[] args) { start(); } private static void start() { String unUsedVariable; System.out.println("Hello, World!"); } private static void unUsedMethod() { } }
После
<empty>
Пункт «Extract/Introduce»
Следующий блок — Extract/Introduce. Думаю, является одним из самых популярных. Позволяет извлекать разные части программы.

Пункт «Variable» (Ctrl+Alt+V)
Создает новую переменную из выделенного фрагмента. (Этому способу у Фаулера посвящена глава “Extract Variable”).
До
public class ExtractVariable { public static void main(String[] args) { sayHello(); } private static void sayHello() { System.out.println("He<caret>llo, World!"); } }
После
public class ExtractVariable { public static void main(String[] args) { sayHello(); } private static void sayHello() { String text = "Hello, World!"; System.out.println(text); } }
Пункт «Constant» (Ctrl+Alt+C)
Создает новую константу из выделенного фрагмента.
До
public class ExtractVariable { public static void main(String[] args) { sayHello(); } private static void sayHello() { System.out.println("He<caret>llo, World!"); } }
После
public class ExtractVariable { public static final String HELLO_WORLD = "Hello, World!"; public static void main(String[] args) { sayHello(); } private static void sayHello() { System.out.println(HELLO_WORLD); } }
Пункт «Field» (Ctrl+Alt+F)
Создает новое поле класса из выделенного фрагмента.
До
public class ExtractVariable { public static void main(String[] args) { sayHello(); } private static void sayHello() { System.out.println("He<caret>llo, World!"); } }
После
public class ExtractVariable { private static String x; public static void main(String[] args) { sayHello(); } private static void sayHello() { x = "Hello, World!"; System.out.println(x); } }
Пункт «Parameter» (Ctrl+Alt+P)
Создает новый параметр (функции) из выделенного фрагмента.
До
public class ExtractVariable { public static void main(String[] args) { sayHello(); } private static void sayHello() { System.out.println("He<caret>llo, World!"); } }
После
public class ExtractVariable { public static void main(String[] args) { sayHello("Hello, World!"); } private static void sayHello(String x) { System.out.println(x); } }
Пункт «Functional Parameter»
Очень похож на пункт «Parameter», но теперь в функцию мы передаем или java.util.function.Supplier, или javafx.util.Builder. Обратите внимание, данный рефакторинг может привести к нежелательным эффектам.
До
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText()); } private static String generateText() { return "Hello, Wor<caret>ld!".toUpperCase(); } }
После
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText(() -> "Hello, World!")); } private static String generateText(final Supplier<string> getText) { return getText.get().toUpperCase(); } }
Пункт «Functional Variable»
Очень похож на пункт «Variable», но теперь мы получаем или java.util.function.Supplier или javafx.util.Builder.
До
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText()); } private static String generateText() { return "Hello, W<caret>orld!".toUpperCase(); } }
После
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText()); } private static String generateText() { Supplier<string> getText = () -> "Hello, World!"; return getText.get().toUpperCase(); } }
Пункт «Parameter Object»
Удобный способ, когда в функцию передается много аргументов и вам надо обернуть их в класс. (У Фаулера это глава “Introduce Parameter Object”).
До
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText("Hello", "World!")); } private static String generateText(Str<caret>ing hello, String world) { return hello.toUpperCase() + world.toUpperCase(); } }
После
public class ExtractParameter { public static void main(String[] args) { System.out.println(generateText(new HelloWorld("Hello", "World!"))); } private static String generateText(HelloWorld helloWorld) { return helloWorld.getHello().toUpperCase() + helloWorld.getWorld().toUpperCase(); } private static class HelloWorld { private final String hello; private final String world; private HelloWorld(String hello, String world) { this.hello = hello; this.world = world; } public String getHello() { return hello; } public String getWorld() { return world; } } }
Пункт «Method» (Ctrl+Alt+M)
Извлекаем метод из выделенного фрагмента. (У Фаулера есть глава про похожий способ рефакторинга — “Extract Function”).
До
public class ExtractMethod { public static void main(String[] args) { String text = "Hello, World!"; System.out.prin<caret>tln(text); } }
После
public class ExtractMethod { public static void main(String[] args) { String text = "Hello, World!"; print(text); } private static void print(String text) { System.out.println(text); } }
Пункт «Type Parameter»
Рефакторинг из мира Kotlin, и для Java не применим (буду рад добавить, если кто-то сделает пример).
Пункт «Replace Method With Method Object»
Оборачивает выделенный фрагмент в объект. Может использоваться, если надо вернуть несколько объектов из метода (возвращает объект-обертку).
До
public class ExtractMethod { public static void main(String[] args) { String text = "Hello, World!"; print(text); } private static void print(String text) { System.out.p<caret>rintln(text); } }
После
public class ExtractMethod { public static void main(String[] args) { String text = "Hello, World!"; print(text); } private static void print(String text) { new Printer(text).invoke(); } private static class Printer { private String text; public Printer(String text) { this.text = text; } public void invoke() { System.out.println(text); } } }
Пункт «Delegate»
Позволяет извлечь методы и поля в отдельный класс.
До
public class Delegate { public static void main(String[] args) { new Delegate().print(); } private void print() { System.ou<caret>t.println("Hello, World!"); } }
После
public class Delegate { private final Printer printer = new Printer(); public static void main(String[] args) { new Delegate().print(); } private void print() { printer.print(); } public static class Printer { public Printer() { } private void print() { System.out.println("Hello, World!"); } } }
Пункт «Interface»
Для заданного класса и его методов создает интерфейс. (Особенно удобно, когда при работе со Spring, когда кто-то забыл для компонента создать соответствующий интерфейс)
До
public class ExtractImpl { public static void main(String[] args) { new ExtractImpl().print(); } public void print() { System.out.println("Hello, World!"); } }
После
public class ExtractImpl implements ExtractInterface { public static void main(String[] args) { new ExtractImpl().print(); } @Override public void print() { System.out.println("Hello, World!"); } } public interface ExtractInterface { void print(); }
Пункт «Superclass»
Аналогично пункту «Interface», только теперь создается класс-родитель (Superclass). Фаулер описывает этот способ рефакторинга в главе “Extract Superclass”.
До
public class ExtractImpl { public static void main(String[] args) { new ExtractImpl().print(); } public void print() { System.out.println("Hello, World!"); } }
После
public class ExtractImpl extends ExtractAbstr { public static void main(String[] args) { new ExtractImpl().print(); } } public class ExtractAbstr { public void print() { System.out.println("Hello, World!"); } }
Пункт «Subquery as CTE»
Относится к Sql, поэтому пропускаю. Если кто-то пришлет пример, хотя бы в виде кода — с удовольствием дополню.
Пункт «RSpec ‘let’»
Относится к Ruby, поэтому пропускаю Если кто-то пришлет пример, хотя бы в виде кода — с удовольствием дополню.
Пункт «Inline»
Возможно один из самых крутых методов рефакторинга, Инлайнить можно почти все. Фаулер описывает этот способ рефакторинга в главах “Inline Class”, “Inline Function”, “Inline Variable”.

Использованный код
До
public class Inline { public static void main(String[] args) { print(); } private static void print() { new Printer().print(); } private static class Printer { public void print() { String text = "Hello, World!"; System.out.println(t<caret>ext); } } }
После
public class Inline { public static void main(String[] args) { System.out.println("Hello, World!"); } }
Пункт «Find and Replace code duplicate»
Ищет похожие фрагменты кода и предлагает заменить их, например, вызовом метода или константой.

Использованный код
До
public class Replace { public static void main(String[] args) { System.out.println("Hello, World!"); } public void print() { System.out.println("Hello, World!"); } public void print2() { System.out.prin<caret>tln("Hello, World!"); } }
После
public class Replace { public static void main(String[] args) { print2(); } public void print() { print2(); } public static void print2() { System.out.println("Hello, World!"); } }
Пункт «Invert Boolean»
Позволяет инвертировать булевые переменные.

Использованный код
До
public class Invert { public static void main(String[] args) { boolean co<caret>ndition = true; if (condition) { System.out.println("Hello, World!"); } } }
После
public class Invert { public static void main(String[] args) { boolean condition = false; if (!condition) { System.out.println("Hello, World!"); } } }
Пункт «Pull Member Up»
Позволяет перемещать методы или поля по иерархии вверх. Зачем это нужно написано у Фаулера в главах “Pull Up Field” и “Pull Up Method”. Выполняет обратную задачу пункта «Pull Member Down».

Использованный код
До
public class PullMethod { public static void main(String[] args) { new InnerClass().print(); } private static class InnerClass extends AbstClass { public void print() { System.out.pri<caret>ntln("Hello, World"); } } private static abstract class AbstClass { } }
После
public class PullMethod { public static void main(String[] args) { new InnerClass().print(); } private static class InnerClass extends AbstClass { } private static abstract class AbstClass { public void print() { System.out.println("Hello, World"); } } }
Пункт «Pull Member Down»
Выполняет обратную задачу пункта «Pull Member Up». Позволяет перемещать методы или поля по иерархии вниз. (У Фаулера — глава “Push Down Method”)

Использованный код
До
public class PullMethod { public static void main(String[] args) { new InnerClass().print(); } private static class InnerClass extends AbstClass { } private static abstract class AbstClass { public void print() { System.out.prin<caret>tln("Hello, World"); } } }
После
public class PullMethod { public static void main(String[] args) { new InnerClass().print(); } private static class InnerClass extends AbstClass { @Override public void print() { System.out.println("Hello, World"); } } private static abstract class AbstClass { public abstract void print(); } }
Пункт «Push ITds In»
Используется при работе с AsperctJ.

Использованный код
До
aspect myAspect { boolean Account.closed = <caret>false; void Account.close() { closed = true; } } class Account { }
После
aspect myAspect { boolean Account.closed = false; } class Account { void close() { closed = true; } }
Пункт «Use Interface Where Possible»
IDEA старается заменить, где это возможно, указания классов на указание интерфейсов.

Использованный код
До
public class ExtractInterface { public static void main(String[] args) { InnerClass innerClass = new InnerClass(); print(innerClass); } private static void print(InnerClass innerClass) { innerClass.print(); } private static class InnerClass implements InnerInterface{ @Override public void print() { System.out.println("Hello, World!"); } } private static interface InnerInterface{ void print(); } }
После
public class ExtractInterface { public static void main(String[] args) { InnerInterface innerClass = new InnerClass(); print(innerClass); } private static void print(InnerInterface innerClass) { innerClass.print(); } private static class InnerClass implements InnerInterface{ @Override public void print() { System.out.println("Hello, World!"); } } private static interface InnerInterface{ void print(); } }
Пункт «Replace Inheritance with Delegation»
Заменяет наследование делегированием. У Фаулера про это главы “Replace Subclass with Delegate” и “Replace Superclass with Delegate”.

Использованный код
До
public class InheritanceDelegation { public static void main(String[] args) { InnerClass innerClass = new InnerClass(); print(innerClass); } private static void print(InnerClass innerClass) { innerClass.print(); } private static class In<caret>nerClass extends AbstractClass { } private static class AbstractClass { public void print() { System.out.println("Hello, World!"); } } }
После
public class InheritanceDelegation { public static void main(String[] args) { InnerClass innerClass = new InnerClass(); print(innerClass); } private static void print(InnerClass innerClass) { innerClass.print(); } private static class InnerClass { private final AbstractClass abstractClass = new AbstractClass(); public void print() { abstractClass.print(); } } private static class AbstractClass { public void print() { System.out.println("Hello, World!"); } } }
Пункт «Remove Middleman»
Заменяет все делегированные вызовы на прямые. (У Фаулера — глава “Remove Middle Man”).

Использованный код
До
public class Middleman { public static void main(String[] args) { InnerClass innerClass = new InnerClass(); innerClass.print(); } private static class InnerClass { private final NextClass next<caret>Class = new NextClass(); public void print() { nextClass.print(); } } private static class NextClass { public void print() { System.out.println("Hello, World!"); } } }
После
public class Middleman { public static void main(String[] args) { InnerClass innerClass = new InnerClass(); innerClass.getNextClass().print(); } private static class InnerClass { private final NextClass nextClass = new NextClass(); public NextClass getNextClass() { return nextClass; } } private static class NextClass { public void print() { System.out.println("Hello, World!"); } } }
Пункт «Wrap Method Return Value»
Оборачивает возвращаемое значение в объект-обертку. Удобно, когда нужно возвращать несколько связанных значений.

Использованный код
До
public class WrapMethodReturnValue { public static void main(String[] args) { System.out.println(new MessageFolder().get()); } private static class MessageFolder { public String get() { ret<caret>urn "Hello, World!"; } } }
После
public class WrapMethodReturnValue { public static void main(String[] args) { System.out.println(new MessageFolder().get().getValue()); } private static class MessageFolder { public Message get() { return new Message("Hello, World!"); } public class Message { private final String value; public Message(String value) { this.value = value; } public String getValue() { return value; } } } }
Пункт «Encapsulate Field»
Скрывает поле за getter, setter.

Использованный код
До
public class EncapsulateField { public static void main(String[] args) { System.out.println(new InnerClass().message); } private static class InnerClass { public String m<caret>essage = "Hello, World!"; } }
После
public class EncapsulateField { public static void main(String[] args) { System.out.println(new InnerClass().getMessage()); } private static class InnerClass { private String message = "Hello, World!"; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } }
Пункт «Replace Temp with Query»
Пусть у вас есть
int size = getActualSize()
с помощью этого способа рефакторинга вы можете заменить использование size на использование метода getActualSize(). Это приведет к увеличению количества вызовов методов, но в некоторых случаях может оказаться полезным. Пример так же показывает возможность извлечения метода с одновременным его дальнейшим использованием.

Использованный код
До
public class ReplaceTemp { public static void main(String[] args) { String hello = "Hello"; String mes<caret>sage = hello + ", World!"; System.out.println(message); } }
После
public class ReplaceTemp { public static void main(String[] args) { String hello = "Hello"; System.out.println(message(hello)); } private static String message(String hello) { return hello + ", World!"; } }
Пункт «Replace Constructor with Factory Method»
Генерирует фабричный метод для указанного конструктора. Идеально, если у вас нет Lombok. (У Фаулера этому посвящена глава “Replace Constructor with Factory Function”).

Использованный код
До
public class ReplaceConstructor { public static void main(String[] args) { new InnerClass("Hello", "World").print(); } private static class InnerClass { private String message; public Inner<caret>Class(String hello, String world) { message = hello + ", " + world; } public void print() { System.out.println(message); } } }
После
public class ReplaceConstructor { public static void main(String[] args) { InnerClass.createInnerClass("Hello", "World").print(); } private static class InnerClass { private String message; private InnerClass(String hello, String world) { message = hello + ", " + world; } public static InnerClass createInnerClass(String hello, String world) { return new InnerClass(hello, world); } public void print() { System.out.println(message); } } }
Пункт «Replace Constructor with Builder»
Генерирует builder для указанного конструктора. Идеально, если у вас нет Lombok.

Использованный код
До
public class ReplaceConstructor { public static void main(String[] args) { new InnerClass("Hello", "World").print(); } private static class InnerClass { private String message; public InnerC<caret>lass(String hello, String world) { message = hello + ", " + world; } public void print() { System.out.println(message); } } }
После
public class ReplaceConstructor { public static void main(String[] args) { new InnerClassBuilder().setHello("Hello").setWorld("World").createInnerClass().print(); } static class InnerClass { private String message; public InnerClass(String hello, String world) { message = hello + ", " + world; } public void print() { System.out.println(message); } } } public class InnerClassBuilder { private String hello; private String world; public InnerClassBuilder setHello(String hello) { this.hello = hello; return this; } public InnerClassBuilder setWorld(String world) { this.world = world; return this; } public ReplaceConstructor.InnerClass createInnerClass() { return new ReplaceConstructor.InnerClass(hello, world); } }
Пункт «Generify»
Пытается код с raw-типами превратить в код с Generic-типами. Актуален при миграции с java версий ранее 1.5 на современные версии.

Использованный код
До
public class Generify { public static void main(String[] args) { List list = getList(); Object message = list.get(0); System.out.println(message); } private static List getList() { ArrayList arrayList = new ArrayList(); arrayList.add("Hello, World!"); return arrayList; } }
После
public class Generify { public static void main(String[] args) { List<string> list = getList(); String message = list.get(0); System.out.println(message); } private static List<string> getList() { ArrayList<string> arrayList = new ArrayList<>(); arrayList.add("Hello, World!"); return arrayList; } }
Пункт «Migrate»
Предоставляет готовые миграции для следующего списка:

А также предоставляет возможность делать свои. Вот, например, правила миграции для JUnit(4.x -> 5.0):
здесь есть подробное видео про миграцию для JUnit(4.x -> 5.0).
Пункт «Lombok» и «Delombok»
Предоставляются плагином “Lombok”. Недавно было объявлено, что теперь он будет входить в стандартную поставку IDEA. Используется при работе с библиотекой кодогенерации “Lombok”.
Пункт «Internationalize»
Используется для интернационализации. К сожалению, в справке не нашел на данный момент информации. IDEA сейчас активно локализуется на другие языки, скорее всего для этого был разработан этот метод.
Список источников
-
Прекрасный доклад про атомарный рефакторинг от Тагира Валеева
-
Refactoring: Improving the Design of Existing Code (Martin Fowler)
ссылка на оригинал статьи https://habr.com/ru/post/530360/
Добавить комментарий