Java 编译器添加了额外的 else 部分并移动了该 else 部分中的最后一个 return 语句
Java Compiler adding additional else part and moving last return statement in that else part
我在 java 技术堆栈中工作了一段时间,但还没有遇到过此类问题。我有一个方法,它在末尾有一个 return 语句,中间有一个 if 语句,没有 else 部分。当我编译我的 class 时,编译器生成一个 class ,其中此方法在末尾和最后一条语句有额外的 else 块(这是我的 return 语句被移入编译器添加的 else 部分) .
我需要了解为什么编译器会做这样的事情,以及导致这种事情的代码有什么问题。
Java 方法
public String convertFromHtmlToDBTextTemplates(final String html, final String convertTo, XPathMapping xPathMapping) {
//Editor specific code to replace Colour classes to Codes classes for DB
String result = colourCodesClassConversion(html, convertTo);
result = result.replaceAll(HTML_START_POINT_UPPER, HTML_START_POINT);
result = result.replaceAll(HTML_SPAN_UPPER_END, HTML_END_POINT);
//Replacing UI Label with the corresponding XPath reading mapping from the passed XPathMapping
if (IMCollectionUtils.isNotEmpty(xPathMapping.getXPathElements().getXPathElement())) {
for (XPathMapping.XPathElements.XPathElement xpathElement : xPathMapping.getXPathElements().getXPathElement()) {
result = result.replaceAll(LESS_THAN_CHARACTER + xpathElement.getUILabel() + GREATER_THAN_CHARACTER,
XPATH_WRAPPER_ELEMENT + xpathElement.getXPath() + CLOSING_BRACKET);
if (xpathElement.getChildElements() != null && IMCollectionUtils.isNotEmpty(xpathElement.getChildElements().getChildElement())) {
for (XPathMapping.XPathElements.XPathElement.ChildElements.ChildElement childElement : xpathElement.getChildElements().getChildElement()) {
if (result.contains(LESS_THAN_CHARACTER
+ xpathElement.getUILabel()
+ UI_LABEL_SEPARATOR
+ childElement.getUILabel()
+ GREATER_THAN_CHARACTER)) {
result = result.replaceAll(
LESS_THAN_CHARACTER
+ xpathElement.getUILabel()
+ UI_LABEL_SEPARATOR
+ childElement.getUILabel()
+ GREATER_THAN_CHARACTER,
XPATH_REPEATING_WRAPPER_ELEMENT
+ xpathElement.getXPath()
+ REPEATING_ENTITY_SEPARATOR
+ childElement.getXPath()
+ CLOSING_BRACKET);
}
}
}
}
}
return result;
}
编译后的代码为
public String convertFromHtmlToDBTextTemplates(String html, String convertTo, XPathMapping xPathMapping) {
String result = this.colourCodesClassConversion(html, convertTo);
result = result.replaceAll("<SPAN", "<span");
result = result.replaceAll("</SPAN>", "</span>");
if (IMCollectionUtils.isNotEmpty(xPathMapping.getXPathElements().getXPathElement())) {
Iterator var5 = xPathMapping.getXPathElements().getXPathElement().iterator();
while(true) {
XPathElement xpathElement;
do {
do {
if (!var5.hasNext()) {
return result;
}
xpathElement = (XPathElement)var5.next();
result = result.replaceAll("<" + xpathElement.getUILabel() + ">", "XPATH:{" + xpathElement.getXPath() + "}");
} while(xpathElement.getChildElements() == null);
} while(!IMCollectionUtils.isNotEmpty(xpathElement.getChildElements().getChildElement()));
Iterator var7 = xpathElement.getChildElements().getChildElement().iterator();
while(var7.hasNext()) {
ChildElement childElement = (ChildElement)var7.next();
if (result.contains("<" + xpathElement.getUILabel() + ":" + childElement.getUILabel() + ">")) {
result = result.replaceAll("<" + xpathElement.getUILabel() + ":" + childElement.getUILabel() + ">", "XPATHRE:{" + xpathElement.getXPath() + "#" + childElement.getXPath() + "}");
}
}
}
} else {
return result;
}
}
'''
反编译代码没有问题。它看起来令人困惑,但 return 语句位于内部 do-while
循环中,而不是在 if
块本身的末尾。
if (...) {
Iterator var5 = ...
while (true) {
XPathElement xpathElement;
do {
do {
if (!var5.hasNext()) {
return result; // return if iterator has no more elements
// this return statement is always reached
}
result = ... // perform first replacement
} while (...); // if there are no child elements continue iteration, otherwise jump to outer do-while loop
} while (...); // if collection is empty continue iteration (this is the && part of your second if statement)
while () { // iterate child element
}
// we are still inside while(true) loop
// jump back to 'XPathElement xpathElement;' line
}
} else {
return result; // this return statement is not needed to complete the if(true) case
}
I need to understand why compiler is doing such thing
引入差异的不是编译器:它是反编译器。
一般来说,有无数个 Java 源代码输入可以产生相同的字节码输出。一个明显的例子是,重命名变量会使字节码保持不变;但存在其他示例,例如 if (condition) return; else statement;
和 if (condition) return; statement;
.
因此,反编译器几乎肯定无法生成您放入编译器的准确源代码。它只能识别字节码中的模式,并说“这个字节码通常是由编写 this... 这样的代码的人产生的”;或者,“这个字节码最简单地是由编写像 this 这样的代码的人生成的”。你可能就是这样写的;可能不是。
在这段代码的情况下:
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
}
return result;
因为while
循环永远无法正常完成(它returns,或者一直循环:条件不变,循环内部没有break),永远不会到达最终的return
;因此 return
实际上在 else
.
中
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
} else {
return result;
}
因此,反编译器生成此代码是因为它是等效的。
我在 java 技术堆栈中工作了一段时间,但还没有遇到过此类问题。我有一个方法,它在末尾有一个 return 语句,中间有一个 if 语句,没有 else 部分。当我编译我的 class 时,编译器生成一个 class ,其中此方法在末尾和最后一条语句有额外的 else 块(这是我的 return 语句被移入编译器添加的 else 部分) . 我需要了解为什么编译器会做这样的事情,以及导致这种事情的代码有什么问题。
Java 方法
public String convertFromHtmlToDBTextTemplates(final String html, final String convertTo, XPathMapping xPathMapping) {
//Editor specific code to replace Colour classes to Codes classes for DB
String result = colourCodesClassConversion(html, convertTo);
result = result.replaceAll(HTML_START_POINT_UPPER, HTML_START_POINT);
result = result.replaceAll(HTML_SPAN_UPPER_END, HTML_END_POINT);
//Replacing UI Label with the corresponding XPath reading mapping from the passed XPathMapping
if (IMCollectionUtils.isNotEmpty(xPathMapping.getXPathElements().getXPathElement())) {
for (XPathMapping.XPathElements.XPathElement xpathElement : xPathMapping.getXPathElements().getXPathElement()) {
result = result.replaceAll(LESS_THAN_CHARACTER + xpathElement.getUILabel() + GREATER_THAN_CHARACTER,
XPATH_WRAPPER_ELEMENT + xpathElement.getXPath() + CLOSING_BRACKET);
if (xpathElement.getChildElements() != null && IMCollectionUtils.isNotEmpty(xpathElement.getChildElements().getChildElement())) {
for (XPathMapping.XPathElements.XPathElement.ChildElements.ChildElement childElement : xpathElement.getChildElements().getChildElement()) {
if (result.contains(LESS_THAN_CHARACTER
+ xpathElement.getUILabel()
+ UI_LABEL_SEPARATOR
+ childElement.getUILabel()
+ GREATER_THAN_CHARACTER)) {
result = result.replaceAll(
LESS_THAN_CHARACTER
+ xpathElement.getUILabel()
+ UI_LABEL_SEPARATOR
+ childElement.getUILabel()
+ GREATER_THAN_CHARACTER,
XPATH_REPEATING_WRAPPER_ELEMENT
+ xpathElement.getXPath()
+ REPEATING_ENTITY_SEPARATOR
+ childElement.getXPath()
+ CLOSING_BRACKET);
}
}
}
}
}
return result;
}
编译后的代码为
public String convertFromHtmlToDBTextTemplates(String html, String convertTo, XPathMapping xPathMapping) {
String result = this.colourCodesClassConversion(html, convertTo);
result = result.replaceAll("<SPAN", "<span");
result = result.replaceAll("</SPAN>", "</span>");
if (IMCollectionUtils.isNotEmpty(xPathMapping.getXPathElements().getXPathElement())) {
Iterator var5 = xPathMapping.getXPathElements().getXPathElement().iterator();
while(true) {
XPathElement xpathElement;
do {
do {
if (!var5.hasNext()) {
return result;
}
xpathElement = (XPathElement)var5.next();
result = result.replaceAll("<" + xpathElement.getUILabel() + ">", "XPATH:{" + xpathElement.getXPath() + "}");
} while(xpathElement.getChildElements() == null);
} while(!IMCollectionUtils.isNotEmpty(xpathElement.getChildElements().getChildElement()));
Iterator var7 = xpathElement.getChildElements().getChildElement().iterator();
while(var7.hasNext()) {
ChildElement childElement = (ChildElement)var7.next();
if (result.contains("<" + xpathElement.getUILabel() + ":" + childElement.getUILabel() + ">")) {
result = result.replaceAll("<" + xpathElement.getUILabel() + ":" + childElement.getUILabel() + ">", "XPATHRE:{" + xpathElement.getXPath() + "#" + childElement.getXPath() + "}");
}
}
}
} else {
return result;
}
}
'''
反编译代码没有问题。它看起来令人困惑,但 return 语句位于内部 do-while
循环中,而不是在 if
块本身的末尾。
if (...) {
Iterator var5 = ...
while (true) {
XPathElement xpathElement;
do {
do {
if (!var5.hasNext()) {
return result; // return if iterator has no more elements
// this return statement is always reached
}
result = ... // perform first replacement
} while (...); // if there are no child elements continue iteration, otherwise jump to outer do-while loop
} while (...); // if collection is empty continue iteration (this is the && part of your second if statement)
while () { // iterate child element
}
// we are still inside while(true) loop
// jump back to 'XPathElement xpathElement;' line
}
} else {
return result; // this return statement is not needed to complete the if(true) case
}
I need to understand why compiler is doing such thing
引入差异的不是编译器:它是反编译器。
一般来说,有无数个 Java 源代码输入可以产生相同的字节码输出。一个明显的例子是,重命名变量会使字节码保持不变;但存在其他示例,例如 if (condition) return; else statement;
和 if (condition) return; statement;
.
因此,反编译器几乎肯定无法生成您放入编译器的准确源代码。它只能识别字节码中的模式,并说“这个字节码通常是由编写 this... 这样的代码的人产生的”;或者,“这个字节码最简单地是由编写像 this 这样的代码的人生成的”。你可能就是这样写的;可能不是。
在这段代码的情况下:
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
}
return result;
因为while
循环永远无法正常完成(它returns,或者一直循环:条件不变,循环内部没有break),永远不会到达最终的return
;因此 return
实际上在 else
.
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
} else {
return result;
}
因此,反编译器生成此代码是因为它是等效的。