Wywołanie metody Java bez nazwy

101

Patrzę na poniższy kod i znalazłem coś trochę dziwnego:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Spodziewałbym się, że spowoduje to błąd kompilacji, ponieważ znak System.outz "y" nie należy do deklaracji metody, tylko do { }. Dlaczego to jest ważne? Nie rozumiem, jak ten kod miałby lub powinien zostać wywołany.

Po uruchomieniu tego generuje x y c grównież, dlaczego static { }get jest wywoływane przed konstruktorem sekwencji?

david99world
źródło

Odpowiedzi:

149

To:

static {
        System.out.print("x ");
    }

jest statycznym blokiem inicjalizacyjnym i jest wywoływana podczas ładowania klasy. Możesz mieć ich tyle w swojej klasie, ile chcesz, a zostaną one wykonane w kolejności ich wyglądu (od góry do dołu).

To:

    {
        System.out.print("y ");
    }

jest blokiem inicjalizacyjnym , a kod jest kopiowany na początek każdego konstruktora klasy. Więc jeśli masz wielu konstruktorów swojej klasy i wszyscy muszą zrobić coś wspólnego na początku, wystarczy napisać kod tylko raz i umieścić go w bloku inicjalizacyjnym, takim jak ten.

Dlatego Twoje wyniki mają sens.

Jak skomentował Stanley poniżej, zobacz sekcję w samouczku Oracle opisującą bloki inicjalizacji, aby uzyskać więcej informacji.

jlordo
źródło
12
Świetna odpowiedź. Więcej informacji o bloku inicjalizacji można znaleźć pod adresem http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley,
6
the code is copied into the beginning of each constructor of the class- to jest niepoprawne. Powiedzmy, że konstruktor zaczyna się od super("x ");, super konstruktor wykona przed jakimikolwiek blokami inicjalizacyjnymi.
RokL
3
tak, niejawne i jawne wywołania superkonstruktora będą wykonywane jako pierwsze, następnie blok inicjalizacji, a następnie reszta kodu konstruktora.
jlordo
25

To nie jest metoda, ale blok inicjalizacji .

 {
    System.out.print("y ");
 }

Zostanie wykonany przed wywołaniem konstruktora. Podczas

static {
        System.out.print("x ");
       }

jest statycznym blokiem inicjalizacyjnym, który jest wykonywany, gdy klasa jest ładowana przez program ładujący klasy.

Więc kiedy uruchamiasz swój kod
1. Klasa jest ładowana przez program ładujący klasy, więc wykonywany jest statyczny blok inicjalizacyjny.
Wyjście: wypisywane jest x
2. Obiekt jest tworzony tak, że wykonywany jest blok inicjalizacyjny, a następnie wywoływany jest konstruktor
Wyjście: drukowane jest y, a następnie c
3. Wywoływana jest metoda główna, która z kolei wywołuje metodę go.
Wyjście: drukowane jest g

Końcowy wynik: xycg
To może pomóc http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

xyz
źródło
@Cthulhu: Dzięki. Była ważna do zeszłego tygodnia zaktualizowałem ją o nowy link.
xyz
16

To blok inicjalizacji wystąpienia, po którym następuje blok inicjalizacji statycznej .

{
    System.out.print("y ");
}

jest wywoływana podczas tworzenia instancji klasy.

static {
    System.out.print("x ");
}

jest wywoływana, gdy klasa jest ładowana przez program ładujący klasy. Więc kiedy to zrobisz

new Sequence().go();

klasa zostaje załadowana, więc jest wykonywana static {}, następnie wykonuje blok inicjalizacji instancji {}, następnie wywoływana jest treść konstruktora, a następnie metoda na nowo utworzonej instancji. Ergo wyjście x y c g.

Luchian Grigore
źródło
15
static {
        System.out.print("x ");
    }

Jest blokiem statycznym i jest wywoływana podczas ładowania klasy

{
    System.out.print("y ");
}

Jest blokiem inicjalizacyjnym

Możesz mieć wiele bloków inicjalizacyjnych w klasie, w którym to przypadku są one wykonywane w kolejności, w jakiej występują w klasie.

Zauważ, że każdy blok inicjalizacji obecny w klasie jest wykonywany przed konstruktorem.

Narendra Pathai
źródło
10
static {
      System.out.print("x ");
}

jest blokiem inicjalizacyjnym współdzielonym przez klasę (jak wskazuje static), który jest wykonywany jako pierwszy.

{
        System.out.print("y ");

}

jest blokiem inicjalizacyjnym współdzielonym przez wszystkie obiekty (konstruktory) klasy, który następuje w następnej kolejności.

Sequence() {
        System.out.print("c ");
}

jest konkretnym konstruktorem dla klasy, która jest wykonywana jako trzecia. Blok inicjalizacji wystąpienia jest wywoływany jako pierwszy za każdym razem, gdy wykonywany jest konstruktor. Dlatego „y” występuje tuż przed „c”.

void go() {
        System.out.print("g ");
}

jest tylko metodą instancji skojarzoną z obiektami zbudowanymi przy użyciu powyższego konstruktora, który jest ostatni.

Terry Li
źródło
9
{
    System.out.print("y ");
}

Tego rodzaju bloki nazywane są initializer block. Jest wykonywany za każdym razem, gdy tworzysz instancję class. W czasie kompilacji ten kod jest przenoszony do każdego konstruktora Twojej klasy.

Gdzie jak w przypadku static initializerbloku: -

static {
    System.out.println("x ");
}

jest wykonywany raz, gdy klasa jest ładowana. Zwykle używamy staticbloku inicjalizatora, gdy inicjalizacja staticpola wymaga wielu kroków.

Rohit Jain
źródło
6

Jest używany jako blok inicjalizacyjny i jest uruchamiany po każdej deklaracji statycznej . Można go użyć, aby upewnić się, że nikt inny nie może utworzyć instancji klasy (w taki sam sposób, w jaki użyłbyś prywatnego konstruktora), jak w przypadku wzorca projektowego Singleton .

maloney
źródło
3
static {
    System.out.print("x ");
}

Static blockssą wykonywane tylko raz, gdy klasa jest ładowana i inicjowana przez środowisko JRE.

I non-staticblok będzie dzwonić za każdym razem, gdy tworzysz nową instancję i to będzie wezwanie tuż przed konstruktora.

Jak tutaj stworzyłeś tylko 1 Sequencetak skonstruowane wystąpienie zostało wywołane po non-staticblokach, a następnie metoda, która faktycznie jest twoim celem.

Subhrajyoti Majumder
źródło