2010-09-10 10 views
32

Czy ktoś wie, dlaczego można odwołać się do metody static w pierwszym wierszu konstruktora przy użyciu this() lub super(), ale nie jest metodą niestatyczną?Dlaczego nie mogę odwołać się do metody instancji podczas jawnego wywoływania konstruktora?

Rozważmy następujący robocza:

public class TestWorking{ 
    private A a = null; 
    public TestWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestWorking(B bParam) 
    { 
     this(TestWorking.getAFromB(bParam)); 
    } 

    //It works because its marked static. 
    private static A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 

i następujący nieprodukcyjnym przykład:

public class TestNotWorking{ 
    private A a = null; 
    public TestNotWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestNotWorking(B bParam) 
    { 
     this(this.getAFromB(bParam)); 
    } 

    //This does not work. WHY??? 
    private A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 
+1

Może to być po prostu przykładowy kod, ale niepokojący bym o tym kodzie był, że masz logikę do skonstruowania instancji 'A' z instancji' B' ukrytej w trzeciej klasie 'TestNotWorking'. –

+0

Zgadzam się z twoją troską. Powód, dla którego robię to w następujący sposób: Używam API innej firmy, który ma ograniczone możliwości w klasie, a klasa jest oznaczona jako ostateczna.Jedynym sposobem było sklonowanie oryginalnego obiektu i praca nad kopią. Użyłem oryginalnego obiektu jako parametru dla mojego nowego obiektu. Na potrzeby przykładu trochę go zmodyfikowałem. – Koekiebox

+0

@Koekiebox Dlaczego zastanawiasz się, że TestNotWorking.getAFromB (bParam) nie działa? to jest metoda instancji. powinieneś stworzyć obiekt lub użyć tego. – gstackoverflow

Odpowiedz

16

metody Non-statyczne metody instancji. Są dostępne tylko w istniejącej instancji, a instancja jeszcze nie istnieje, gdy jesteś w konstruktorze (jest on wciąż w budowie).

Dlaczego tak się dzieje? Ponieważ metody instancji mogą uzyskiwać dostęp do pól instancji (niestatycznych), które mogą mieć różne wartości w różnych instancjach, więc nie ma sensu wywoływanie takiej metody na czymś innym niż istniejąca, ukończona instancja.

+28

To jest blisko, ale nie jest dokładne. Instancje * do * istnieją, gdy znajdujesz się w konstruktorze, a Ty * możesz * wywoływać na nich metody instancji. Ale nie możesz tego zrobić, dopóki nie zakończy się konstruktor super-klasy. Jeśli chcesz wywołać je w swoim własnym konstruktorze, jest to w porządku, ale super klasa musi zostać ukończona. – erickson

+0

To nie jest dokładna odpowiedź. Komentarz również nie jest całkowicie trafny, ponieważ pytanie nie dotyczy wywoływania super konstruktora, ale konstruktora z tej samej klasy, oczywiście dlatego, że najpierw potrzebujemy super-konstruktora, ale odpowiedź i komentarz nie mówią jasno. –

+0

Co z tym kodem? ** class ClassForTest { ClassForTest (int k) { }; { metoda(); } ClassForTest() { to (1); }; int metoda() {return 1;}} ** – gstackoverflow

1

Myślę, że to dlatego, że zmienne końcowe instancji nie są jeszcze ustawione (więc nie masz jeszcze instancji), a metoda instancji może uzyskać do niej dostęp. Natomiast wszystkie inicjalizacje statyczne zostały wykonane przed wywołaniem konstruktora.

Greetz, Ghad

1

bo gdy dzwonisz to w konstruktorze lub super Twój obiekt nie został jeszcze zbudowany. (Twoja instancja nie jest jeszcze całkowicie zainicjalizowana). więc wywołanie metody instancji nie tworzy sceny.

0

Jeśli metoda jest niestatyczna, należy wywołać ją na obiekcie.

W drugim przykładzie należy utworzyć obiekt klasy TestNotWorking i wywołać getAFromB na tym obiekcie.

Coś jak:

object = new TestNotWorking(); 
object.getAFromB(bParam); 
1

TestNotWorking nie jest inicjowany w tym punkcie. Problem polega na tym, że pierwszy konstruktor (TestNotWorking (A aParam)) może wywoływać super() (wewnętrznie zawsze), co oznacza, że ​​wywołasz metodę przed wywołaniem konstruktora nadklasy. To nielegalne.

11

Zobacz Java Language Specification 8.8.7.1. Ten stwierdza, że ​​

Wyraźne oświadczenie konstruktor inwokacja w ciele konstruktora nie może odnosić się do wszelkich zmiennych instancji lub metod instancji klas wewnętrznych zgłoszonych w tej klasie lub jakiejkolwiek nadrzędnej lub użyj this lub super w każdej wypowiedzi; w przeciwnym razie wystąpi błąd podczas kompilacji.

Dzieje się tak dlatego, że nie można wywołać metody instancji przed utworzeniem instancji. Nawiasem mówiąc, możliwe jest wywołanie metody instancji później w konstruktorze (chociaż nie jest to rozwiązanie dla ciebie).

+0

** lub użyj tego lub super w dowolnym wyrażeniu; w przeciwnym razie wystąpi błąd podczas kompilacji ** proszę wyjaśnić – gstackoverflow

+0

@Marc, co oznacza, że ​​wystąpienie jest tworzone w stercie po wykonaniu jawnego/niejawnego wywołania konstruktora nadklasy, mimo że jego inicjalizacja jeszcze się nie zakończyła? – dannail

Powiązane problemy