I want to change .class file’s method. I installed JD Eclipse Decompiler and opened the .class file. I added some codes and save .class file. But, .class file is not changing.
I don’t know how to use decompiler. And if is it possible, how to change .class file without using decompiler.
I am using Ubuntu.
Regards
EDIT:
Here is my decompiled code:
/* */ package org.hibernate.id;
/* */
/* */ import java.io.Serializable;
/* */ import java.sql.ResultSet;
/* */ import java.sql.SQLException;
/* */ import java.util.HashMap;
/* */ import java.util.Properties;
/* */ import org.apache.commons.logging.Log;
/* */ import org.apache.commons.logging.LogFactory;
/* */ import org.hibernate.HibernateException;
/* */ import org.hibernate.MappingException;
/* */ import org.hibernate.dialect.Dialect;
/* */ import org.hibernate.type.Type;
/* */ import org.hibernate.util.ReflectHelper;
/* */
/* */ public final class IdentifierGeneratorFactory
/* */ {
/* 25 */ private static final Log log = LogFactory.getLog(IdentifierGeneratorFactory.class);
/* */
/* 64 */ private static final HashMap GENERATORS = new HashMap();
/* */
/* 66 */ public static final Serializable SHORT_CIRCUIT_INDICATOR = new Serializable() {
/* */ public String toString() { return "SHORT_CIRCUIT_INDICATOR";
/* */ }
/* 66 */ };
/* */
/* 70 */ public static final Serializable POST_INSERT_INDICATOR = new Serializable() {
/* */ public String toString() { return "POST_INSERT_INDICATOR";
/* */ }
/* 70 */ };
/* */
/* */ public static Serializable getGeneratedIdentity(ResultSet rs, Type type)
/* */ throws SQLException, HibernateException, IdentifierGenerationException
/* */ {
/* 32 */ if (!(rs.next())) {
/* 33 */ throw new HibernateException("The database returned no natively generated identity value");
/* */ }
/* 35 */ Serializable id = get(rs, type);
/* */
/* 37 */ if (log.isDebugEnabled()) log.debug("Natively generated identity: " + id);
/* 38 */ return id;
/* */ }
/* */
/* */ public static Serializable get(ResultSet rs, Type type)
/* */ throws SQLException, IdentifierGenerationException
/* */ {
/* 45 */ Class clazz = type.getReturnedClass();
/* 46 */ if (clazz == Long.class) {
/* 47 */ return new Long(rs.getLong(1));
/* */ }
/* 49 */ if (clazz == Integer.class) {
/* 50 */ return new Integer(rs.getInt(1));
/* */ }
/* 52 */ if (clazz == Short.class) {
/* 53 */ return new Short(rs.getShort(1));
/* */ }
/* 55 */ if (clazz == String.class) {
/* 56 */ return rs.getString(1);
/* */ }
if(clazz == java.math.BigDecimal.class){
return rs.getBigDecimal(1);
}
/* */
/* 59 */ throw new IdentifierGenerationException("this id generator generates long, integer, short or string78");
/* */ }
/* */
/* */ public static IdentifierGenerator create(String strategy, Type type, Properties params, Dialect dialect)
/* */ throws MappingException
/* */ {
/* */ try
/* */ {
/* 92 */ Class clazz = getIdentifierGeneratorClass(strategy, dialect);
/* 93 */ IdentifierGenerator idgen = (IdentifierGenerator)clazz.newInstance();
/* 94 */ if (idgen instanceof Configurable) ((Configurable)idgen).configure(type, params, dialect);
/* 95 */ return idgen;
/* */ }
/* */ catch (Exception e) {
/* 98 */ throw new MappingException("could not instantiate id generator", e);
/* */ }
/* */ }
/* */
/* */ public static Class getIdentifierGeneratorClass(String strategy, Dialect dialect) {
/* 103 */ Class clazz = (Class)GENERATORS.get(strategy);
/* 104 */ if ("native".equals(strategy)) clazz = dialect.getNativeIdentifierGeneratorClass();
/* */ try {
/* 106 */ if (clazz == null) clazz = ReflectHelper.classForName(strategy);
/* */ }
/* */ catch (ClassNotFoundException e) {
/* 109 */ throw new MappingException("could not interpret id generator strategy: " + strategy);
/* */ }
/* 111 */ return clazz;
/* */ }
/* */
/* */ public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
/* 115 */ if (clazz == Long.class) {
/* 116 */ return new Long(value);
/* */ }
/* 118 */ if (clazz == Integer.class) {
/* 119 */ return new Integer((int)value);
/* */ }
/* 121 */ if (clazz == Short.class) {
/* 122 */ return new Short((short)(int)value);
/* */ }
/* */
/* 125 */ throw new IdentifierGenerationException("this id generator generates long, integer, short");
/* */ }
/* */
/* */ static
/* */ {
/* 75 */ GENERATORS.put("uuid", UUIDHexGenerator.class);
GENERATORS.put("hilo", TableHiLoGenerator.class);
GENERATORS.put("assigned", Assigned.class);
GENERATORS.put("identity", IdentityGenerator.class);
GENERATORS.put("select", SelectGenerator.class);
GENERATORS.put("sequence", SequenceGenerator.class);
GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);
GENERATORS.put("increment", IncrementGenerator.class);
GENERATORS.put("foreign", ForeignGenerator.class);
GENERATORS.put("guid", GUIDGenerator.class);
GENERATORS.put("uuid.hex", UUIDHexGenerator.class);
GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);
}
}
- #2
Собственно, перерыл весь интернет, и никак не пойму… как отредактировать вот эти переменные в файле .class
Посмотреть вложение 37913В программе Recaf даже редактировать могу, но не сохраняется при экспорте. Пробовал Эклипс — там вообще нет возможности редактировать (или я не нашел). В интернете нашел Java ByteCod Editor и DirtyJoe, у них получается редактировать только методы. А вот эти строчки переменные редактировать там возможности нет.
Подскажите, пожалуйста, чем и как редактировать эти переменные, выделенные на фото?
class — это скомпилированный файл. Его редактирование не допустимо. Тебе нужно для начала декомпилировать сборку, потом отдельно собирать класс и добавлять его с заменой старого в свой jar файл через WinRar.
- #3
декомпил, правка, повторный компил.
но делать так не советую — декомпиляторы не идеальны и вполне могут внести какие нибудь неочевидные косяки, которые повторному компилу не помешают, но вот получившийся код будет работать криво.
З.Ы. можно еще попробовать на лету, при загрузке сервера, менять значения переменых, если они не final.
- #4
Deom, Gaikotsu, что-то я так и не понял… как в итоге заменить значения то? Чем редактировать? Достать и обратно засунуть файл class через WinRar я понял, а вот чем декомпилировать и редактировать?
- #5
Deom, Gaikotsu, что-то я так и не понял… как в итоге заменить значения то? Чем редактировать? Достать и обратно засунуть файл class через WinRar я понял, а вот чем декомпилировать и редактировать?
у вас готовый класс в редакторе. копируем содержимое создаем файл с таким же названием и расширением .java редактируем ну и потом пытаемся скомпилить.
- #6
Ну если нужно просто поменять значения переменных, то в данном случае, в другом классе из датапака, который запускается и компилится при запуске серва просто делаем типа
Код:
MailBBSManager.EXPOSTB_COIN = 57;
Ведь эти переменные public и значит видны извне
- #7
LifeGame32, сделал так, отредактировал, попытался скомпилить с помощью javac и вот что выдает:
Файлы в итоге остались без изменений
- #8
Gaikotsu, про датапак и про «при запуске сервера», к сожалению, ничего не понял
- #9
Gaikotsu, про датапак и про «при запуске сервера», к сожалению, ничего не понял
мозги чуть-чуть напрягать полезно, особенно когда тебе готовые методы подсказывают), но если в двух словах — тебе нужен открытый скрипт в сборку (ЛЮБОЙ СКРИПТ В КОТОРЫЙ ТЫ ПИХАЕШЬ ЭТОТ public) — с измененным значением выше, и при загрузке сервера твой скрипт будет значение заменять на нужное, и будет грузиться не то что скомпилено в основном классе.
- #10
мозги чуть-чуть напрягать полезно, особенно когда тебе готовые методы подсказывают), но если в двух словах — тебе нужен открытый скрипт в сборку (ЛЮБОЙ СКРИПТ В КОТОРЫЙ ТЫ ПИХАЕШЬ ЭТОТ public) — с измененным значением выше, и при загрузке сервера твой скрипт будет значение заменять на нужное, и будет грузиться не то что скомпилено в основном классе.
сейчас бы тратить время на люцеру, дык еще и без сурса
- #11
Deom, Gaikotsu, что-то я так и не понял… как в итоге заменить значения то? Чем редактировать? Достать и обратно засунуть файл class через WinRar я понял, а вот чем декомпилировать и редактировать?
По поводу декомпила есть статья на хабре
Вы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация
- #12
LifeGame32, сделал так, отредактировал, попытался скомпилить с помощью javac и вот что выдает:
Посмотреть вложение 37914
Файлы в итоге остались без изменений
javac -classpath ************.jar -Xlint:unchecked -encoding utf8 **********.java
Также лучше используй 2 декомпила (есть онлайн), они могут отличаться от того, что ты видишь.
Например ->
Вы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация
- #13
Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Собственно, перерыл весь интернет, и никак не пойму… как отредактировать вот эти переменные в файле .class
Посмотреть вложение 37913В программе Recaf даже редактировать могу, но не сохраняется при экспорте. Пробовал Эклипс — там вообще нет возможности редактировать (или я не нашел). В интернете нашел Java ByteCod Editor и DirtyJoe, у них получается редактировать только методы. А вот эти строчки переменные редактировать там возможности нет.
Подскажите, пожалуйста, чем и как редактировать эти переменные, выделенные на фото?
ты не соберешь обратно этот фаил так как при декомпиляции отвалятся некоторые куски кода которые нужно будет восстанавливать саморучно
- #14
сейчас бы тратить время на люцеру, дык еще и без сурса
Для чувака который понятия не имеет что такое .class вполне пойдет как для начала. Все когда-то свои пути ковыряния начинали с подобного)
- #15
Теперь вообще все накрылось тазом…
Геймсервер при запуске выдает:
Unrecognized VM option ‘UseFastAccessorMethods’
Error: Could not create the Java Virtual Machine.
Что делать? Удалить JDK?
Argest, честно говоря, скачал сборку в шаре по запросу «создать свой сервер л2». То, что это оказалась сборка Lucera 1.7 я узнал лишь тогда, когда начал шерстить этот форум. Потратил больше недели на настройку сборки и уже как-то не хотелось искать другую сборку и заново всё перенастраивать… Пока в планах добить люцеру, а в следующий раз уже буду получше думать над выбором сборки
Последнее редактирование модератором: 11 Июл 2021
- #16
Ежики плакали, но продолжали жрать кактус…
Брать сборку без исходников, если в планах что-то в ней менять — ну такое себе…
- #17
Gaikotsu, так я же говорю, брал сборку по запросу «создать свой сервер л2» ))) По гайду 2014 года с нулём знаний о создании серверов. Неделю самостоятельно ковырялся, а потом уже пошел сюда за ответами на непонятные мне вопросы
Rolo
Поклонник кармы
- #18
accavit, если всего неделю — много сделать не успели, лучше пока не поздно взять что угодно другое (в рамках разумного и с пометкой «для тренировки», а не лайва) с исходниками, всяко продуктивней, чем обучаться на перспективу страдать ерундой с декомпилом.
- #19
Rolo, так вроде с декомпилом разобрался… Только вот геймсервер теперь вроде пытается запуститься через JDK и не может:
Unrecognized VM option ‘UseFastAccessorMethods’
Error: Could not create the Java Virtual Machine.
Удаляю JDK — всё работает. Вот думаю, может для компила вместо javac использовать что-то другое?
- #20
UseFastAccessorMethods опция
Вы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация
и была
Вы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация
в JDK 9. Вам необходимо удалить эту опцию из конфигурации запуска.
- HowTo
- Java Howtos
- Class File Editor in Java
Rupam Yadav
Dec 19, 2022
Dec 15, 2021
- Features of Java Class File Editor
- Using Java Class File Editor to Edit a Compiled Java Class
In this article, we will discuss the Java Class File Editor, a tool created in Java used to edit Java compiled classes. We can decompile and see the Java classes once they are created, but we need tools like the Java Class File Editor to modify them.
Features of Java Class File Editor
- Easy to use Interface built using Java Swing
- Allows modifications of various parts of a class file, like methods, strings, constants, etc.
- Consistency Checks
Using Java Class File Editor to Edit a Compiled Java Class
-
Download Java Class File Editor from https://sourceforge.net/projects/classeditor/files/
-
Extract the compressed file, and open the JAR file name
ce.jar
shown below.
If we are unable to open the file, we can open the command line/terminal and use the following command: -
Once the editor is opened, we open a Java class file using the
File > Open
menu item and choose the explorer class file. -
We will use the following code in the class file.
public class ExampleClass1 { private static final String METHOD_NAME1 = "exampleMethod1"; private static final String METHOD_NAME2 = "exampleMethod2"; public static void main(String[] args) { int abc = 200; System.out.println(abc); exampleMethod2(); } static void exampleMethod2() { System.out.println("This is just a method"); } }
-
After the editor opens the file, we turn on the Modify Mode in the top-right corner; this mode is off by default, as shown in the image below. The button will turn blue if it is on and green if it is off.
-
After the modification is on, we can modify certain aspects of the class by going to different editor sections.
The General section of the editor shows the class name and its parent class. We can see and edit the interfaces if any are in the class. Class Access Modifiers are also there, which we can change if we want to.
The next section is the Constant Pool section, which displays all the editor’s constants in the class. Here we can change the type of the constant and its value. We can add new constants or delete an existing one.
The Fields section of the editor shows the fields with their access modifiers which we can modify.
The last section of the editor part is the Methods section, where all the class methods are listed with their name, access modifiers, and return types that are all editable, and we can change them. -
After all the modifications, we save the class file using the
File > Save
menu item. We can also export all the items like the name of fields, constants, methods, and their values as an XML file using theFile > Export to XML
menu item.
Rupam Saini is an android developer, who also works sometimes as a web developer., He likes to read books and write about various things.
I want to update a .class file in a jar with a new one. What is the easiest way to do it, especially in the Eclipse IDE?
asked Nov 3, 2009 at 12:51
0
This tutorial details how to update a jar file
jar -uf jar-file <optional_folder_structure>/input-file(s)
where ‘u’ means update.
GC_
4383 silver badges22 bronze badges
answered Nov 3, 2009 at 13:14
Brian AgnewBrian Agnew
266k36 gold badges331 silver badges439 bronze badges
7
Do you want to do it automatically or manually? If manually, a JAR file is really just a ZIP file, so you should be able to open it with any ZIP reader. (You may need to change the extension first.) If you want to update the JAR file automatically via Eclipse, you may want to look into Ant support in Eclipse and look at the zip task.
answered Nov 3, 2009 at 12:54
JasCavJasCav
34.2k20 gold badges110 silver badges168 bronze badges
Simply drag and drop your new class file to the JAR using 7-Zip or Winzip. You can even modify a JAR file that is included in a WAR file using the parent folder icon, and click Ok when 7zip detects that the inside file has been modified
answered Nov 3, 2009 at 13:47
LastnicoLastnico
1,47311 silver badges13 bronze badges
2
- Use
jar -xvf
to extract the files to a directory. - Make your changes and replace the classes.
- Use
jar -cvf
to create a new jar file.
answered Oct 21, 2014 at 19:23
James LimJames Lim
12.9k3 gold badges39 silver badges64 bronze badges
Jar is an archive, you can replace a file in it by yourself in your favourite file manager (Total Commander for example).
answered Nov 3, 2009 at 12:55
silentsilent
3,77323 silver badges29 bronze badges
A JAR file is just a .zip in disguise. The zipped folder contains .class
files.
If you’re on macOS:
- Rename the file to possess the ‘.zip’ extension. e.g. myJar.jar -> myJar.zip.
- Decompress the ‘.zip’ (double click on it). A new folder called ‘myJar’ will appear
- Find and replace the
.class
file with your new .class file. - Select all the contents of the folder ‘myJar’ and choose ‘Compress x items’. DO NOT ZIP THE FOLDER ITSELF, ONLY ITS CONTENTS
Miscellaneous — Compiling a single .class file, with reference to a original jar, on macOS
- Make a file myClass.java, containing your code.
- Open terminal from Spotlight.
javac -classpath originalJar.jar myClass.java
This will create your compiled class called myClass.class.
From here, follow the steps above. You can also use Eclipse to compile it, simply reference the original jar by right clicking on the project, ‘Build Path’ -> ‘Add External Archives’. From here you should be able to compile it as a jar, and use the zip technique above to retrieve the class from the jar.
answered Sep 12, 2016 at 20:42
Toby MellorToby Mellor
7,9668 gold badges35 silver badges57 bronze badges
Editing properties/my_app.properties file inside jar:
"zip -u /var/opt/my-jar-with-dependencies.jar properties/my_app.properties"
. Basically "zip -u <source> <dest>"
, where dest is relative to the jar extract folder.
answered Dec 22, 2017 at 10:03
Shashi RanjanShashi Ranjan
1,4716 gold badges25 silver badges51 bronze badges
High-level steps:
Setup the environment
Use JD-GUI to peek into the JAR file
Unpack the JAR file
Modify the .class file with a Java Bytecode Editor
Update the modified classes into existing JAR file
Verify it with JD-GUI
Refer below link for detailed steps and methods to do it,
https://www.talksinfo.com/how-to-edit-class-file-from-a-jar/
answered Nov 25, 2018 at 20:47
1) you can extract the file into a folder called
jarname.jar
and then replace the file in the folder, handy if you are updating the class a lot while debugging
2) you can extract the jar replace the file then the jar it up again
3) Open the jar with 7 zip and drag and drop your new class in to copy over the old one
answered Nov 3, 2009 at 13:19
Craig AngusCraig Angus
22.5k18 gold badges55 silver badges63 bronze badges
You can find source code of any .jar file online, import the same project in your IDE with basic setups. Make necessary changes in .java file and compile it for .class files.
Once compilation is done You need to extract the jar file, replace the old .class file with new one.
And use below command for reconstruct .jar file
Jar cf test.jar *
Note : I have done so many time this changes in our project, hope you will find it useful.
answered Mar 22, 2018 at 10:07
harihari
1442 silver badges9 bronze badges
An alternative is not to replace the .class file in the jar file. Instead put it into a new jar file and ensure that it appears earlier on your classpath than the original jar file.
Not sure I would recommend this for production software but for development it is quick and easy.
answered Nov 3, 2009 at 13:56
I want to update a .class file in a jar with a new one. What is the easiest way to do it, especially in the Eclipse IDE?
asked Nov 3, 2009 at 12:51
0
This tutorial details how to update a jar file
jar -uf jar-file <optional_folder_structure>/input-file(s)
where ‘u’ means update.
GC_
4383 silver badges22 bronze badges
answered Nov 3, 2009 at 13:14
Brian AgnewBrian Agnew
266k36 gold badges331 silver badges439 bronze badges
7
Do you want to do it automatically or manually? If manually, a JAR file is really just a ZIP file, so you should be able to open it with any ZIP reader. (You may need to change the extension first.) If you want to update the JAR file automatically via Eclipse, you may want to look into Ant support in Eclipse and look at the zip task.
answered Nov 3, 2009 at 12:54
JasCavJasCav
34.2k20 gold badges110 silver badges168 bronze badges
Simply drag and drop your new class file to the JAR using 7-Zip or Winzip. You can even modify a JAR file that is included in a WAR file using the parent folder icon, and click Ok when 7zip detects that the inside file has been modified
answered Nov 3, 2009 at 13:47
LastnicoLastnico
1,47311 silver badges13 bronze badges
2
- Use
jar -xvf
to extract the files to a directory. - Make your changes and replace the classes.
- Use
jar -cvf
to create a new jar file.
answered Oct 21, 2014 at 19:23
James LimJames Lim
12.9k3 gold badges39 silver badges64 bronze badges
Jar is an archive, you can replace a file in it by yourself in your favourite file manager (Total Commander for example).
answered Nov 3, 2009 at 12:55
silentsilent
3,77323 silver badges29 bronze badges
A JAR file is just a .zip in disguise. The zipped folder contains .class
files.
If you’re on macOS:
- Rename the file to possess the ‘.zip’ extension. e.g. myJar.jar -> myJar.zip.
- Decompress the ‘.zip’ (double click on it). A new folder called ‘myJar’ will appear
- Find and replace the
.class
file with your new .class file. - Select all the contents of the folder ‘myJar’ and choose ‘Compress x items’. DO NOT ZIP THE FOLDER ITSELF, ONLY ITS CONTENTS
Miscellaneous — Compiling a single .class file, with reference to a original jar, on macOS
- Make a file myClass.java, containing your code.
- Open terminal from Spotlight.
javac -classpath originalJar.jar myClass.java
This will create your compiled class called myClass.class.
From here, follow the steps above. You can also use Eclipse to compile it, simply reference the original jar by right clicking on the project, ‘Build Path’ -> ‘Add External Archives’. From here you should be able to compile it as a jar, and use the zip technique above to retrieve the class from the jar.
answered Sep 12, 2016 at 20:42
Toby MellorToby Mellor
7,9668 gold badges35 silver badges57 bronze badges
Editing properties/my_app.properties file inside jar:
"zip -u /var/opt/my-jar-with-dependencies.jar properties/my_app.properties"
. Basically "zip -u <source> <dest>"
, where dest is relative to the jar extract folder.
answered Dec 22, 2017 at 10:03
Shashi RanjanShashi Ranjan
1,4716 gold badges25 silver badges51 bronze badges
High-level steps:
Setup the environment
Use JD-GUI to peek into the JAR file
Unpack the JAR file
Modify the .class file with a Java Bytecode Editor
Update the modified classes into existing JAR file
Verify it with JD-GUI
Refer below link for detailed steps and methods to do it,
https://www.talksinfo.com/how-to-edit-class-file-from-a-jar/
answered Nov 25, 2018 at 20:47
1) you can extract the file into a folder called
jarname.jar
and then replace the file in the folder, handy if you are updating the class a lot while debugging
2) you can extract the jar replace the file then the jar it up again
3) Open the jar with 7 zip and drag and drop your new class in to copy over the old one
answered Nov 3, 2009 at 13:19
Craig AngusCraig Angus
22.5k18 gold badges55 silver badges63 bronze badges
You can find source code of any .jar file online, import the same project in your IDE with basic setups. Make necessary changes in .java file and compile it for .class files.
Once compilation is done You need to extract the jar file, replace the old .class file with new one.
And use below command for reconstruct .jar file
Jar cf test.jar *
Note : I have done so many time this changes in our project, hope you will find it useful.
answered Mar 22, 2018 at 10:07
harihari
1442 silver badges9 bronze badges
An alternative is not to replace the .class file in the jar file. Instead put it into a new jar file and ensure that it appears earlier on your classpath than the original jar file.
Not sure I would recommend this for production software but for development it is quick and easy.
answered Nov 3, 2009 at 13:56
Эту статью можно рассматривать как краткий обзор 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)
Содержание
Введение
Раздел «Refaсtor»
— Refactor This
— Rename
— Rename File
— Change Signature
— Edit Property Value (без примера)
— Type Migration
— Make Static
— Convert To Instance Method
— Move Classes
— Copy Classes
— Safe Delete
— Extract/Introduce
— — Variable
— — Constant
— — Field
— — Parameter
— — Functional Parameter
— — Functional Variable
— — Parameter Object
— — Method
— — Type Parameter (без примера)
— — Interface
— — Superclass
— — Subquery as CTE (без примера)
— — RSpec ‘let’ (без примера)
— Inline
— Find and Replace Code Duplicate
— Pull Member Up
— Pull Member Down
— Push ITds In
— Use Interface Where Possible
— Replace Inheritance with Delegation
— Remove Middleman
— Wrap Method Return Value
— Encapsulate Field
— Replace Temp with Query
— Replace Constructor with Factory Method
— Replace Constructor with Builder
— Generify
— Migrate
— 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();
}
}
ParameterObject
Пункт «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 сейчас активно локализуется на другие языки, скорее всего для этого был разработан этот метод.
Список источников
-
Прекрасный доклад про атомарный рефакторинг от Тагира Валеева
-
Справка IDEA
-
Refactoring: Improving the Design of Existing Code (Martin Fowler)
-
На данный момент я знаю о InClassTranslator что в принципе не поможет проблеме. Он просто удаляет содержимое переменной,а не вывод её самой.
Таким образом есть программка, которая позволяет просматривать содержимое самих классов т.е. исходник код ява-скрипта: jd-gui .Полезная штука. С помощью её нахожу код, который нужно отредактировать или удалить, но становится вопрос: Как это сделать? Можно ли Eclipc-ом, и как это сделать что бы потом скомпилировать обратно в .class без ошибок?
Еще есть такая штука как MCP которая распакует за вас весь клиент майна и у вас будет возможность редактировать файлы формата .java с чем Eclipc или любой другой Ide редактор справится без каких либо проблем. Но не так то все просто. Сам по себе MCP не всегда может правильно распаковать и запаковать клиент, т.к. есть множество обстоятельств :
— Если клиент с модами;
— Если вы уже что-то правили левыми путями;
— Если IDE редактору что-то не понравится, то он просто напросто вас пошлет. Возможно это моя недоработка за счет малоопытности в dev-java , но все же.В целом нужна помощь старожил в этом плане.
-
Code
Старожил
Пользователь- Баллы:
- 123
- Имя в Minecraft:
- _Gizmo
декомпилируешь нужный класс jd-gui, пихаешь содержимое в .java файлик с соответствующим названием, через консоль пишешь javac -cp джарки название.java, где джарки это список джарок с импортированными классами через ; потом смотришь ошибки, исправляешь, и снова javac. потом можешь вносить изменения и снова компилировать.
-
хм. Спасибо. Сейчас так и попробую сделать. А на счет Eclipc-а не знаешь? мб есть возможность сделать это через визуальную часть?
-
Code
Старожил
Пользователь- Баллы:
- 123
- Имя в Minecraft:
- _Gizmo
можно просто создать новый проект, в нем создать нужный класс, а используемые джарки подключить как библиотеки
-
Вот не до конца все понял. Я декомпильнул файлик. Теперь у меня есть bkg.class в нем есть такое кол-во импортов, их всех надо вписывать в cmd при запросе?
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import cpw.mods.fml.client.GuiModList;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU; -
В результате :
Cmd -> javac -cp import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import cpw.mods.fml.client.GuiModList;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU; bkg.java -
Code
Старожил
Пользователь- Баллы:
- 123
- Имя в Minecraft:
- _Gizmo
нет, нужно записать туда имена джарок, в которых эти классы лежат и которые не входят в стандартный набор библиотек. то есть minecraft.jar;lwjgl.jar и так далее.
-
Будь прокляты мои познания в яве. Вроде бы что-то читал да и делал.
Как узнать, какие джарки использует под себя, скажем bkg.java ? -
Code
Старожил
Пользователь- Баллы:
- 123
- Имя в Minecraft:
- _Gizmo
это по импортируемым классам определяется. классы, лежащие в java.* (и еще некоторые) лежат в стандартных библиотеках, для них ничего не надо писать, по остальным кассам просто смотришь в какой джарке они лежат и вписывешь ее.
пропиши туда все из папки bin, этого точно хватит чтобы покрыть весь импорт -
Ukranos45
Активный участник- Баллы:
- 78
- Skype:
- maksim.kakashi
- Имя в Minecraft:
- Ukranos
Поделиться этой страницей
Modify your Java class files easy with an interactive GUI.
Since it is not possible to edit a class file directly, this tool changes the class file to Smali version which is editable. After making the required changes, this tool converts the modified Smali to the modified Class file.
Features:
- Modify a given Java class file
- Allows Pen-tester to verify if their java desktop application is safe from Auth bypass
- Can help you change the logical behavior of a Jar file by modifying a class
- You can override private methods, change access modifier for variables of a class using ClassModifier.
- Many other possibilities….
Download ClassModifier:
How to Use:
java -jar ClassModifier.jar
Menu:
File
- Open class (CTRL+O)- Takes the input class which need to be modified
- Open Project (CTRL+P)– You can reopen the project created using this feature.
- Save & Convert (CTRL+S) – Saves & Convert the code to modified Class and Smali file
- Export Class (CTRL+E) – Export modified class
- Java 2 Smali Helper — Opens a tab where you can write any Java code which on saving will show its equivalent Smali code
- Smali 2 Java code — Opens a tab where you can write any Smali code which on saving will show its equivalent Java code
Edit
- Increase Code FontSize (CTRL+I) – Allows you to increase font size of shown code.
- Decrease Code FontSize (CTRL+D) – Allows you to decrease the font size of shown code.
- Remove all tabs – Removes all currently shown tabs.
Decompiler
- Change Decompiler – Allows you to switch between jadx and jd-cli decompilers.
Help
- Update Software – Helps you to update the current software if any update is available
- How to use Class Modifier– Contains the documentation of this tool
Toolbar
- Allows you to find in current code/replace/replaceAll/find all class
ClassModifier_lib Folder
- It comes along with the software
- Contains the helper jars used by program
- ClassModifier_libuserLibrary is automatically added in classpath while compiling code. If you wish to compile your code using external jars then place those external jars inside ClassModifier_libuserLibrary
How to Use:
- Open the Java class to be Modified
- On opening, ClassModifier will open the Smali version of the class file
- Edit the smali file and make the required changes
- Save the smali file
- Modified java class file will be created which can be anytime exported using the File -> Export Class button.
- Since Smali editing can be difficult, 2 options are provided — Java 2 Smali Helper and vice-versa.
- As name suggests, Java 2 Smali Helper lets you see the Smali equivalent code for the input Java code.
- Similarly, Smali 2 Java Helper lets you see the Java equivalent code for the input Smali code.
Screenshot:
Note: This software is meant for educational purpose only. Don’t use it for any illegal activity.