2011-11-17 9 views
18

w oficjalnym przewodniku Java “Programming with assertions” stwierdza się, że (ostatni akapit na stronie)„Kilka programiści są świadomi faktu, że konstruktorzy i metody klasie może uruchomić przed jego inicjalizacji”

Niewielu programistów zdajemy sobie sprawę z tego, że konstruktory i metody klasy mogą działać przed jej zainicjowaniem. Kiedy tak się dzieje, jest całkiem prawdopodobne, że niezmienniki klasy nie zostały jeszcze ustalone, co może spowodować poważne i subtelne błędy.

Co to oznacza? Kiedy to się dzieje? Czy jest to coś, o co muszę dbać w codziennym korzystaniu z Javy?

Odpowiedz

29

Zasadniczo, mówią o następującej sytuacji:

public class Foo { 
    public static Foo INSTANCE = new Foo(); // Prints null 

    public static String s = "bar"; 

    public Foo() { 
     System.out.println(s); 
    } 
} 

Jak widać, w tym przypadku konstruktora biegnie przed inicjator pola statycznego s, i. mi. przed pełną inicjalizacją klasy. To tylko prosty przykład, ale może stać się bardziej skomplikowany, gdy zaangażowanych jest wiele klas.

Nie jest to coś, co często można zobaczyć w codziennej pracy, ale należy pamiętać o tej możliwości i unikać jej podczas pisania kodu.

5

Jako przykład rozważ transmisję metody wirtualnej w konstruktorze.

class Foo { 
    Foo() { 
     int a = bar();   
     b = 7; 
    } 

    private int b; 

    protected int baz() { assert b == 7; return b; } ; 

    protected abstract int bar(); 
} 

Jeśli podklasą się zadzwonić baz z poziomu ich realizacji bar oni uderzyć twierdzenie. Obiekt nie zakończył budowy, więc klasa podstawowa Foo jest w pewnym stanie.

0

Myślę, że to oznacza logiczną inicjalizację. Na przykład twoja klasa A ma metodę init(), która musi zostać wywołana przed użyciem jakichkolwiek metod biznesowych. Ale inny programista, który używa tej klasy, nie przeczytał instrukcji i napisał: new A().foo(). Prawdopodobnie w tym przypadku foo() nie może działać poprawnie. W takim przypadku przydatne może być asercje. Na początku możesz sprawdzić, czy nie zostało wywołane init() i podać asercji.

To samo dotyczy konstruktorów. Może się to zdarzyć, gdy ktoś przedłuży twoją klasę A:

class B extends A { 
    B() { 
     foo(); // init() must be called before foo! 
    } 
} 
+0

co to jest inicjalizacja logiczna (w przeciwieństwie do samego inicjowania)? – scravy

Powiązane problemy