Есть ли использование свободно плавающего блока внутри метода в Java?

Я не знал, что у методов могут быть такие плавающие блоки:

class X { 
    public static void main( String [] args ) {
        { //<--- start
            int i;
        } //<-- ends
    }
}

Я знал о плавающих блоках вне методов, но никогда не пробовал их внутри.

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

Есть ли использование для плавающих блоков внутри методов в Java?

Ответы

Ответ 1

Есть ли использование?

Да - ограничить область локальных переменных.

Это хорошая идея?

Вероятно, спорный (и, скорее всего, будет).

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

Лично я использую их, например:

public void doGet(
        final HttpServletRequest request,
        final HttpServletResponse response)
  throws IOException {
    final PersistenceManager pm = PMF.get().getPersistenceManager();

    final List<ToDoListGaejdo> toDoLists;
    {
        final Query query = pm.newQuery(ToDoListGaejdo.class);
        query.setOrdering("listName asc");
        toDoLists = (List<ToDoListGaejdo>) query.execute();
    }

    final List<ToDoItemGaejdo> entries;
    {
        final Query query = pm.newQuery(ToDoItemGaejdo.class);
        query.setOrdering("listName asc, priority asc");
        entries = (List<ToDoItemGaejdo>) query.execute();
    }

    final ServletOutputStream out = response.getOutputStream();

    out.println("<head>");
    out.println("  <title>Debug View</title>");
    ....

Ответ 2

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

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

Ответ 3

Да, они полезны для двух целей.

Во-первых, вы можете ограничить объем переменных, используя такие блоки. Это может помочь в удобочитаемости кода, потому что у вас есть небольшая область, которую следует учитывать при определении того, как используется переменная. Кроме того, это может свести к минимуму необходимое количество "слотов" для кадра метода, сохраняя пространство стека. Я был бы очень удивлен, найдя случай, когда эта оптимизация была необходима.

Во-вторых, когда вы прикрепляете метку к блоку, целевой блок break можно использовать внутри блока для перехода в конец блока. Это не так злобно, как безупречный оператор goto, но прицел по-прежнему вызывает красные флаги и предупреждающие колокола.

Ответ 4

Еще один случай, когда блоки полезны, заключен в операторах switch; например следующее недопустимо

    switch (i) {
      case 1:
        float j = ...;
        break;
      case 2:
        float j = ...;  // compilation error
        break;
      ...
    }

но это нормально с добавленными блоками:

    switch (i) {
      case 1:
        {
          float j = ...;
          break;
        }
      case 2:
        {
          float j = ...;  // just fine
          break;
        }
      ...
    }

Этот вид использования возникает, когда вы реализуете такие вещи, как государственные машины и интерпретаторы, использующие (большие) операторы switch. Вы можете утверждать, что локальные переменные должны иметь разные имена, но:

  • используя одно и то же имя для той же концепции (хотя и в другой области) в gnarly-коде, как это хорошо для широкомасштабной читаемости, и
  • Использование блоков упрощает компиляторы распознавать, что объявленные переменные могут совместно использовать слоты фреймов стека. Это потенциально важно, если метод включения также рекурсивный.

(ОК, это все либо микро-оптимизация, либо следствие микро-оптимизации. Но предположим, что мы определили, что это оправдано.)