Що означають самі фігурні дужки на Java?


79

У мене є код Java, який використовує фігурні дужки двома способами

// Curly braces attached to an 'if' statement:
if(node.getId() != null)
{
    node.getId().apply(this);
}

// Curly braces by themselves:
{
    List<PExp> copy = new ArrayList<PExp>(node.getArgs());
    for(PExp e : copy)
    {
        e.apply(this);
    }
}
outAMethodExp(node);

Що означають ці самостійні фігурні дужки після першого ifвисловлювання?

Відповіді:


120

Єдина мета додаткових фігурних дужок - вказати обмеження обсягу. List<PExp> copyБуде існувати тільки в межах цих дужок, і не буде мати ніякої можливості поза ними.

Якщо це генерується код, я припускаю, що генератор коду робить це, щоб він міг вставити деякий код (наприклад, цей), не турбуючись про те, скільки разів він вставляв a, List<PExp> copyі не турбуючись про можливе перейменування змінних, якщо цей фрагмент вставляється в один і той же метод більше одного разу.


9
Додатковою "перевагою" в цьому випадку є те, що copyсміття може бути зібране до outAMethodExp()повернення. Якщо це тривалий дзвінок або дзвінок із великою пам’яттю, це може бути корисно. Я вкладаю "вигоду" в лапки, оскільки рефакторинг на окремі методи, як правило, набагато чіткіший та зрозуміліший, ніж використання цього синтаксису.
dimo414

1
Насправді, масштабування змінної не впливає на збір сміття. У всіх сучасних JVM, про які мені відомо, JIT може визначити, що об’єкт придатний для GC, незалежно від наявності або відсутності конструкцій обсягу, таких як фігурні дужки.
Даніель Приден

27

Я дружую те, що написав matt b, і додам, що ще одне використання анонімних фігурних дужок - це оголошення неявного конструктора в анонімних класах. Наприклад:

  List<String> names = new ArrayList<String>() {
    // I want to initialize this ArrayList instace in-line,
    // but I can't define a constructor for an anonymous class:
      {
        add("Adam");
        add("Eve");
      }

  };

Деякі фреймворки модульного тестування підняли цей синтаксис на інший рівень, що дозволяє працювати деяким витонченим речам, які виглядають абсолютно некомпільованими. Оскільки вони виглядають незнайомими, я сам не такий великий шанувальник, але варто хоча б усвідомити, що відбувається, якщо ви натрапите на це використання.


Вибачте, я не розумію цей код. Це "додати" клас або функцію. Якщо це функція: до якого класу вона належить? Чи приймає ArrayList тип делегата в цьому випадку?
Пітер Мортенсен,

7
"додати" - це функція. Матеріали в фігурних дужках викликаються перед конструктором для виконання попередньої ініціалізації. Ви можете переглянути c2.com/cgi/wiki?DoubleBraceInitialization, щоб дізнатися більше.
Завен Нагапетян,

1
Технічно конструктор викликається першим, а блок ініціалізації екземпляра викликається відразу після виклику super(...).
Олі,

8

Я погоджуюсь з відповіддю на обмеження обсягу, але додаю одне.

Іноді ви бачите подібну конструкцію в коді людей, які люблять складати розділи свого коду і мають редактори, які автоматично складатимуть фігурні дужки. Вони використовують його для складання свого коду в логічні розділи, які не потрапляють до функції, класу, циклу тощо, які зазвичай складаються.


4

Я б насправді здогадався, що хтось забув інше твердження.

Рідко буває вагома причина, щоб навіть заморочитися створенням додаткових обсягів блоків. У цьому та більшості випадків набагато частіше хтось, можливо, забув ввести свою заяву контролю, ніж те, що робив щось розумне.


2
Я голосую за вас просто тому, що це може статися, сталося, і Оккам котиться у своїй могилі, бо вас проголосували проти. :)
willasay, що

1
Він генерується SableCC. Б'юся об заклад, 5 доларів вони не забули іншого
Павел Фельдман

Додаткові фігурні дужки корисні для запобігання повзунню глобальних змінних довгим методом, коли ви хочете зберегти кілька схожих блоків коду в одному місці, де блоки недостатньо складні, щоб виправдовувати нові методи.
jayunit100

Я відзначаю курсові роботи Java в університеті, і я бачу, що насправді це часто точна причина, чому вона міститься в коді. При повторному розкладі факторів люди іноді вирізують / вставляють, а потім бачать неправильну кількість фігурних дужок, .. просто додайте одну в .., тоді подивіться, з чим ви закінчите. З цієї причини я голосую за це. Не завжди інше твердження, але часто просто проста помилка.
ThePerson

Я підтримав вас, бо -1 голос означає, що ви навіть не повинні брати участь. Можливо, ви не знали, але доклали зусиль. Я не про трофеї для всіх, але "дякую" - це саме те, що я кажу людям, які намагаються допомогти. (+1 == дякую).
user426364 02

2

Вони роблять внутрішній розмах. Змінна, оголошена всередині цих фігурних дужок, не видно поза ними. Це також стосується C / C ++.


1

Фігурні дужки також корисні для зменшення обсягу в операторах перемикач / регістр.

switch(foo) {
  case BAR:
     int i = ...
     ...
  case BAZ:
     int i = ... // error, "i" already defined in scope
}

Але ти можеш писати

switch(foo) {
  case BAR:{
     int i = ...
     ...
  }
  case BAZ:{
     int i = ... // OK
  }
}

1

Він також використовується для блоків ініціалізації .


Можливо, варто згадати, що це лише для ініціалізації статичного класу поза конструктором. Фрагмент коду OPs знаходиться в блоці методів (лише можливе місце для нього).
mmoore

Блок ініціалізації для статичної ініціалізації класу , якщо він передує в staticіншому випадку його екземпляр ініціалізації блоку.
Габріель

Справжні казки. Дякую за роз'яснення.
mmoore

0

Вони визначають нову область дії, що означає, що все, що заявлено в цій області, не видно поза фігурними дужками.


0

Як цікаве зауваження: фігурні дужки насправді дозволяють класу операторів: оголошення.

Це незаконно: if(a) int f;

але це законно: if(a) { int f; }


Саме цей код марний, ви не зможете побачити f поза фігурними дужками. І для його використання вам потрібно оголосити і використовувати його в тому ж обсязі. Отже, вам потрібно більше одного твердження, тому вам потрібні фігурні дужки.
Павло Фельдман

це суть перевірки компілятора, про яку я згадую. Мені цікаво, що існує різниця у "неявному обсязі" (яким я вважаю кожен однорядковий без фігурних дужок) та явному. Легко забути, що компілятор змінить ситуацію.
Гюго

А як щодо if (userWantsTocInReport) {new Toc (report};}?) Я не кажу, що це ідеальний спосіб написати це, але це можливість, яку хтось може вибрати з будь-якої причини.
user625488


0

Принесіть розмах, копія не буде видно за її межами, тому ви можете оголосити іншу змінну з тим самим іменем пізніше. І його може зібрати збирач сміття відразу після того, як ви вийдете з цієї сфери. У цьому випадку копія служить тимчасовою змінною, тому це хороший приклад.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.