Попробуйте Catch и, наконец, с операторами возврата

Я видел пару таких хитрых фрагментов кода, пока готовился к сертификации по Java.

Возвращаемое значение в конце здесь: 10, но, наконец, вызывается и изменяет returnval на 20.

Может кто-нибудь объяснить, почему это так? это потому, что catch имеет другую область действия returnval ? или я что-то пропустил здесь.

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, что имеет смысл, поскольку finally изменяет значение returnval, и оно сохраняется.

Любое объяснение будет полезно.

я понимаю, что это плохо написанный код, и никто в здравом уме не должен писать ничего подобного.


person Amit Vig    schedule 14.03.2014    source источник


Ответы (2)


В первом примере finally ничего не меняет, потому что 10 уже помечено как значение, возвращаемое внутри оператора catch. Если вы добавите return в блок finally или удалите return из catch и оставите только последний оператор возврата, вы получите значение 20. Самое главное, что вы возвращаете здесь только значение, а не ссылку.

С другой стороны, во втором примере StringBuilder является изменяемым, а returnVal является ссылкой на объект. Затем returnVal со значением «10» помечается как возвращаемое значение, но перед печатью значения returnVal внутри основного метода выполняется блок finally, который изменяет значение returnVal с «10» на «1010». Затем, если вы напечатаете returnVal внутри основного метода, вы получите последнее значение этого объекта, равное «1010». Это работает так, потому что getStringBuilder возвращает ссылку на StringBuilder, которая может быть изменена.

person Jakub H    schedule 14.03.2014
comment
Я не думал об этой стороне. Спасибо, что указали на это. - person Amit Vig; 14.03.2014

Здесь многое происходит, но я думаю, что все сводится к тому, что в версии 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 Идентификационный хэш returnVal в finally: 2116610996 Возвращаемое значение сейчас: 20 В основном: 10

Идентификационный хэш returnVal: 814397217 О возврате: 10 Идентификационный хеш returnVal в блоке catch: 814397217 Возвращаемое значение сейчас: 1010 Идентификационный хэш returnVal в finally: 814397217 В Main: 1010

Идентификационный хэш returnVal: 1660743788 1660743788 Идентификационный хеш returnVal в блоке catch: 1660743788 О возврате: 10 Идентификационный хэш returnVal в finally: 1660743788 Возвращаемое значение сейчас: 20 20

person rainkinz    schedule 14.03.2014
comment
это делает вещи более ясными. Спасибо - person Amit Vig; 14.03.2014