2008-10-27 8 views
66

ich einige Java-Code haben, die geschweiften Klammern auf zwei ArtenWas bedeuten geschweifte Klammern in Java für sich?

// 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); 

Was diese Stand-alone geschweiften Klammern nach dem ersten if Aussage bedeuten, verwendet?

Antwort

105

Der einzige Zweck der zusätzlichen Klammern ist die Angabe des Gültigkeitsbereichs. Die List<PExp> copy wird nur innerhalb dieser geschweiften Klammern existieren und wird keinen Bereich außerhalb von ihnen haben.

Wenn dies Code generiert wird, nehme ich an, der Code-Generator tut dies, so dass es einige Code (wie diese) einfügen kann, ohne sich darum kümmern, wie oft es eine List<PExp> copy eingefügt hat und ohne um mögliche Umbenennung kümmern die Variablen, wenn dieses Snippet mehrmals in dieselbe Methode eingefügt wird.

+5

Ein weiterer "Vorteil" ist in diesem Fall, dass 'copy' Müll vor' outAMethodExp (gesammelt werden können) 'kehrt zurück. Wenn dies ein lang andauernder oder speicherintensiver Aufruf ist, kann das hilfreich sein. Ich gebe "Nutzen" in Anführungszeichen, weil das Refactoring in separate Methoden generell viel sauberer und übersichtlicher ist, als diese Syntax zu nutzen. – dimo414

+0

Tatsächlich wirkt sich das Scoping einer Variablen ** nicht ** auf die Garbage Collection aus. In allen modernen JVMs, die mir bekannt sind, kann das JIT feststellen, ob ein Objekt für GC in Frage kommt, unabhängig davon, ob Rahmenkonstruktionen wie geschweifte Klammern vorhanden oder nicht vorhanden sind. –

2

Sie machen einen inneren Bereich. Die in diesen Klammern deklarierte Variable ist außerhalb von ihnen nicht sichtbar. Dies gilt auch für C/C++.

0

Ich denke, sie definieren nur eine unbenannte Ebene des Umfangs.

0

Sie definieren einen neuen Bereich, was bedeutet, dass alles, was in diesem Bereich deklariert ist, nicht außerhalb der geschweiften Klammern sichtbar ist.

4

Ich würde tatsächlich vermuten, dass jemand eine andere Aussage vergessen hat.

Es gibt selten einen guten Grund, sich überhaupt mit der Erstellung zusätzlicher Blockbereiche zu befassen. In diesen und in den meisten Fällen ist es viel wahrscheinlicher, dass jemand vergessen hat, seine Kontrollaussage einzugeben, als dass er etwas Cleveres getan hat.

+2

Ich wähle dich einfach weil es passieren kann, ist passiert, und Occam rollt in seinem Grab, weil du abgelehnt wurdest. :) – willasaywhat

+1

Es wird von SableCC generiert. Ich wette 5 $ sie haben nicht vergessen, sonst –

+0

Zusätzliche Klammern sind nützlich, um zu verhindern, dass globale Variablen auf Sie in einer langen Methode, wo Sie ein paar, ähnliche Code-Blöcke alle an der gleichen Stelle, wo die Blöcke nicht bleiben wollen komplex genug, um neue Methoden zu rechtfertigen. – jayunit100

0

Das Bring ein Scope, Kopie wird außerhalb davon nicht sichtbar sein, so dass Sie später eine andere Variable mit demselben Namen deklarieren können. Und es kann direkt nach dem Verlassen dieses Bereichs vom Garbage Collector erfasst werden. In diesem Fall Kopie dient als temporäre Variable, so ist es ein gutes Beispiel.

0

Als eine interessante Anmerkung: die Klammern aktivieren tatsächlich eine Klasse von Anweisungen: Deklarationen.

Dies ist illegal: if(a) int f;

aber das ist legal: if(a) { int f; }

+0

Genau dieser Code ist nutzlos, Sie können f nicht außerhalb von geschweiften Klammern sehen. Und um es zu verwenden, müssen Sie es innerhalb desselben Bereichs deklarieren und verwenden. Du brauchst also mehr als eine Aussage, also brauchst du Klammern. –

+0

das ist der Punkt der Compilerüberprüfung, die ich erwähne. Ich finde es interessant, dass es einen Unterschied im "impliziten Umfang" gibt (den ich jeden Einstrich ohne Klammern betrachte) und explizite. Es ist leicht zu vergessen, dass der Compiler einen Unterschied machen würde. – Hugo

+0

Was ist mit if (userWantsTocInReport) {new Toc (report};}? Ich sage nicht, dass es der ideale Weg ist, es zu schreiben, aber es ist eine Möglichkeit, die jemand aus welchem ​​Grund auch immer wählen mag. – user625488

24

ich zweite, was matt b geschrieben, und ich will hinzufügen, dass eine anderweitige Verwendung ich von anonymen Klammern gesehen habe, ist ein implizites zu erklären Konstruktor in anonymen Klassen. Zum Beispiel:

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"); 
     } 

    }; 

Einige Einheit-Test-Frameworks haben diese Syntax auf eine andere Ebene genommen, die einige glatte Dinge erlaubt, die völlig uncompilable aussehen zu arbeiten. Da sie aussehen nicht vertraut sind, bin ich nicht so ein großer Fan selbst, aber es lohnt sich zumindest zu erkennen, was vor sich geht, wenn Sie über diese Verwendung stoßen.

+0

Es tut mir leid, tue ich nicht Verstehen Sie diesen Code. Ist "add" eine Klasse oder eine Funktion. Wenn es eine Funktion ist: Zu welcher Klasse gehört sie? Wird ArrayList in diesem Fall einen Delegattyp akzeptieren? –

+7

"add" ist eine Funktion geschweifte Klammern werden vor dem Konstruktor aufgerufen, um eine vorläufige Initialisierung durchzuführen.Weitere Informationen finden Sie unter http://www.c2.com/cgi/wiki?DoubleBraceInitialization –

+1

Technisch wird der Konstruktor zuerst aufgerufen und der Instanzinitialisierungsblock wird sofort aufgerufen nach dem Aufruf von 'super (...)'. – Oli

7

Ich stimme mit der Umfangsbegrenzung überein, aber würde eine Sache hinzufügen.

Manchmal sehen Sie ein Konstrukt wie dieses im Code von Leuten, die Teile ihres Codes falten möchten und Editoren haben, die Klammern automatisch falten. Sie verwenden es, um ihren Code in logische Abschnitte zu falten, die nicht in eine Funktion, Klasse, Schleife usw. fallen, die normalerweise zusammengefaltet werden würden.

0

Es wird auch für initialization blocks verwendet.

+0

Vielleicht erwähnenswert, dass dies nur für die statische Klasseninitialisierung außerhalb des Konstruktors gilt. OPs Code Snippet befindet sich in einem Methodenblock (nur möglich pl Ass für es). – mmoore

+0

Ein Initialisierungsblock ist für die Initialisierung der statischen Klasse vorgesehen, wenn er mit 'static' vorangestellt ist, andernfalls ein Initialisierungsblock _instance_. – Gabriel

+0

Wahre Geschichten. Danke für die Klarstellung. – mmoore

0

Klammern sind auch nützlich, um den Umfang von Schalter-/Gehäuseanweisungen zu reduzieren.

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

Aber man kann schreiben

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