Я видел пару таких хитрых фрагментов кода, когда я готовился к сертификации Java.
Возвращаемое значение в конце здесь: 10, но, наконец, вызывается и изменяет returnval на 20.
Может кто-нибудь объяснить, почему это так? это потому, что улов имеет разную область возврата? или я что-то пропустил здесь.
class MultipleReturn {
int getInt() {
int returnVal = 10;
try {
String[] students = {"Harry", "Paul"};
System.out.println(students[5]);
}
catch (Exception e) {
System.out.println("About to return :" + returnVal);
return returnVal;
}
finally {
returnVal += 10;
System.out.println("Return value is now :" + returnVal);
}
return returnVal;
}
public static void main(String args[]) {
MultipleReturn var = new MultipleReturn();
System.out.println("In Main:" + var.getInt());
}
}
Другой следующий фрагмент кода:
class MultipleReturn {
StringBuilder getStringBuilder() {
StringBuilder returnVal = new StringBuilder("10");
try {
String[] students = {"Harry", "Paul"};
System.out.println(students[5]);
}
catch (Exception e) {
System.out.println("About to return :" + returnVal);
return returnVal;
}
finally {
returnVal.append("10");
System.out.println("Return value is now :" + returnVal);
}
return returnVal;
}
public static void main(String args[]) {
MultipleReturn var = new MultipleReturn();
System.out.println("In Main:" + var.getStringBuilder());
}
}
здесь выход равен 1010, что имеет смысл, так как окончательно модифицирует returnval и сохраняется.
Любое объяснение будет полезно.
я понимаю, что это плохо написанный код, и никто в здравом уме не должен писать ничего подобного.
В первом примере, finally
ничего не изменится, потому что 10 уже помечено как значение, возвращаемое во внутреннюю инструкцию catch
. Если вы добавите return
к блоку finally
или удалите return
из catch
и оставите только последний оператор возврата, вы получите значение 20. Самое главное, что вы возвращаете только значение, а не ссылку здесь.
С другой стороны, во втором примере StringBuilder является mutable и returnVal является ссылкой на объект. Чем returnVal со значением "10" помечен как возвращаемое значение, но перед тем, как вы напечатаете значение returnVal внутри основного метода, finally
блок выполняется и изменяет значение returnVal с "10" на "1010". Затем, если вы напечатаете returnVal внутри основного метода, вы получите последнее значение этого объекта, которое равно "1010". Это работает так, потому что getStringBuilder
возвращает ссылку на StringBuilder, которая изменена.
Здесь многое происходит, но я думаю, что это сводится к тому, что в версии getStringBuilder объект returnVal изменен и один и тот же объект мутирован в предложении finally, возвращая "1010", как вы заметили. С другой стороны, при добавлении 10 в целое число в ваш предложение finally возвращается другое значение, которое имеет другой адрес в памяти, чем возвращаемое значение.
Попробуйте запустить следующий код, чтобы лучше проиллюстрировать.
class MultipleReturn {
int getInt() {
int returnVal = 10;
System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
try {
String[] students = { "Harry", "Paul" };
System.out.println(students[5]);
} catch (Exception e) {
System.out.println("About to return :" + returnVal);
System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
return returnVal;
} finally {
returnVal += 10;
System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
System.out.println("Return value is now :" + returnVal);
}
return returnVal;
}
StringBuilder getStringBuilder() {
StringBuilder returnVal = new StringBuilder("10");
System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
try {
String[] students = { "Harry", "Paul" };
System.out.println(students[5]);
} catch (Exception e) {
System.out.println("About to return :" + returnVal);
System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
return returnVal;
} finally {
returnVal.append("10");
System.out.println("Return value is now :" + returnVal);
System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
}
return returnVal;
}
static class MutableInteger {
public int val;
@Override
public String toString() {
return Integer.toString(val);
}
}
MutableInteger getMutableInt() {
MutableInteger returnVal = new MutableInteger();
returnVal.val = 10;
System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
System.out.println(System.identityHashCode(returnVal));
try {
String[] students = { "Harry", "Paul" };
System.out.println(students[5]);
} catch (Exception e) {
System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
System.out.println("About to return :" + returnVal);
return returnVal;
} finally {
returnVal.val += 10;
System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
System.out.println("Return value is now :" + returnVal);
}
return returnVal;
}
public static void main(String args[]) {
MultipleReturn var = new MultipleReturn();
System.out.println("In Main:" + var.getInt());
System.out.println();
System.out.println("In Main:" + var.getStringBuilder());
System.out.println();
System.out.println(var.getMutableInt());
}
}
Результаты:
Идентификационный хеш returnVal: 1152321476 О возврате: 10 Идентификационный хеш returnVal в блоке catch: 1152321476 Идентификатор hash returnVal в конце: 2116610996 Возвращаемое значение сейчас: 20 In Main: 10
Идентичный хеш returnVal: 814397217 О возврате: 10 Идентификационный хэш returnVal в блоке catch: 814397217 Возвращаемое значение сейчас: 1010 Идентификационный хеш returnVal в конце: 814397217 В начало: 1010
Идентичный хеш returnVal: 1660743788 1660743788 Идентификационный хеш returnVal в блоке catch: 1660743788 О возврате: 10 Идентификационный хеш returnVal в конце: 1660743788 Возвращаемое значение сейчас: 20 20