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?

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.


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/


@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.


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.


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.


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.


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 .


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.