Как уже указывали другие: декомпилятор (обычно) не может различить разные исходные коды, которые приводят к одному и тому же байтовому коду.
К сожалению, вы не предоставили полный код метода.Таким образом, следующее содержит некоторые предположения о том, где и как этот цикл появляется внутри метода (и эти предположения могут в некоторой степени исказить результат).
Но давайте посмотрим на некоторые поездки туда и обратно.Рассмотрим следующий класс, содержащий методы с обеими версиями кода, который вы опубликовали:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String[] colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String[] colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Компиляция его с помощью
javac DecompileExample.java -g:none
создаст соответствующий файл класса.(Примечание: параметр -g:none
приведет к тому, что компилятор пропустит всю отладочную информацию. Отладочная информация может в противном случае использоваться декомпилятором для реконструкции более дословной версии исходного кода, в частности, включая исходныйимена переменных)
Теперь, глядя на байт-код обоих методов, с
javap -c DecompileExample.class
получим следующее:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
и
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(Там есть небольшая разница: String[] colArr = null
переводится в
aconst null
astore_3
в начале второй версии. Но это один из аспектов, которыйсвязанные с частями кода, которые вы пропустили в вопросе.)
Вы не упомянули, какой из них вы используете, но декомпилятор JD-GUI из http://jd.benow.ca/ декомпилирует это в следующее:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String[] arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String[] arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
Вы можете видеть, что код одинаков для обоих случаев (по крайней мере, в отношении цикла - есть еще одно различие в отношении "фиктивных переменных", которые мне пришлось ввести в ordeг, чтобы скомпилировать его, но это не имеет отношения к вопросу, так сказать).
Сообщение tl; dr ясно:
Различные исходные коды могут быть скомпилированы в один и тот же байт-код.Следовательно, один и тот же байт-код может быть декомпилирован в различные исходные коды.Но каждый декомпилятор должен согласиться на одну версию исходного кода.
(Примечание: я был немного удивлен, увидев, что при компиляции без -g:none
(то есть, когда сохраняется отладочная информация), JD-GUI даже каким-то образом удается восстановить то, что использовался первымwhile
-loop, а второй использовал for
-loop. Но в общем случае, когда отладочная информация опущена, это просто больше невозможно.