I am working in java tech stack for a quite while but have not seen such type issue. I have a method which has a return statement at the end and an if statement in between without else part. When I compile my class, compiler generates a class where this method has additional else block at the end and last statement (which is my return statement is moved into else part added by compiler). I need to understand why compiler is doing such thing and what's wrong with the code which makes it to such thing.
Java Method
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;
}
Compiled code is
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;
}
}
'''
I need to understand why compiler is doing such thing
The compiler isn't the thing that's introducing the difference: it's the decompiler.
In general, there are an infinite number of Java source code inputs that can produce the same bytecode output. The obvious example of this is that renaming a variable leaves the bytecode unchanged; but other examples exist, such as if (condition) return; else statement;
and if (condition) return; statement;
.
As such, the decompiler almost certainly cannot produce the exact source code you put into the compiler. It can only recognise patterns in the bytecode, and say "this bytecode is most often produced by people writing code like this..."; or, "this bytecode is most simply produced by people writing code like this". That may be how you wrote it; it may not be.
In the case of this code:
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
}
return result;
Because the while
loop can never complete normally (it returns, or keeps looping: the condition is constant, and there is no break inside the loop), it never reaches the final return
; so that return
is effectively in an else
.
if (condition) {
while (true) {
if (condition2) {
return result;
}
}
} else {
return result;
}
So, the decompiler produces this code because it is equivalent.