2012-03-20 10 views
31

Powiedz, że definiuję klasę, która jako członek jest zmienną tego samego typu, co ona sama.W jaki sposób klasa może mieć członka własnego typu, czy nie jest to nieskończona rekursja?

public class abc { 
    private abc p; 
} 

To naprawdę działa, ku mojemu zaskoczeniu.

Dlaczego myślę, że nie powinno: tworzenie instancji abc, zawiera zmienną typu abc, który zawiera zmienną typu abc, który zawiera zmienną typu abc, która .....

Oczywiście jestem w błędzie, czy ktoś mógłby mnie oświecić, jak?

+1

Dobre pytanie, ale pamiętaj, aby wrócić do wcześniejszych pytań i zaakceptować odpowiedź dla każdego z nich (łącznie z tym pytaniem). –

+0

Ponieważ w języku Java zmienna typu 'abc' nie zawiera obiektu' abc'. Zmienna typu 'abc' zawiera * odwołanie do * obiektu' abc'. Twoje rozumowanie byłoby ważne, powiedzmy C++. – immibis

Odpowiedz

28

Deklarujesz tylko zmienną i jej nie tworzysz. Spróbuj utworzyć go w deklaracji lub w konstruktorze i daj mi znać, co się dzieje:

public class Abc { 
    private Abc p = new Abc(); // have fun! 

    public static void main(String[] args) { 
     new Abc(); 
    } 
} 

Nawiasem mówiąc, jeśli nie tworzyć go w klasie, ale raczej przyjąć odniesienie do niego w sposób pochłaniacza lub konstruktora parametr, twój kod będzie działał dobrze. Tak działają niektóre połączone listy.

+7

Jesteś zabawny m & $^# &% & @ (# r. Ale widzę twój punkt widzenia, więc dziękuję – jason

+1

@jason: jesteś bardzo mile widziany, jestem tego pewien! –

+1

Każdy, kto szuka właściwej odpowiedzi powinien hava rzucić okiem na [odpowiedź z @David Rodríguez - dribe] (http://stackoverflow.com/questions/13607757/object-of-class-as-instance-variable-inside-the-class?lq=1 # answer-13608203), którą sam HovercraftFullOfEels awansował: – duleshi

8

Jeśli chcesz modelować rzeczywiste scenariusze, być może będziesz musiał użyć tego pojęcia. Na przykład pomyśl o gałęzi Drzewa. W gałęzi drzewa może znajdować się liczba gałęzi. Albo z tła informatyki, pomyśl o węźle listy połączonej. Węzeł będzie miał odniesienie do węzła obok niego. Na końcu, następny będzie zawierał wartość zerową wskazującą koniec listy.

Jest to zatem tylko odniesienie, które wskazuje, że ten typ może odnosić się do jednego z nich. Nic więcej.

19

Różnica polega na sprawdzaniu kompilacji w czasie pracy.

W pierwszym przypadku (czas kompilacji) deklarujesz, że w tym przypadku będziesz miał odwołanie do wartości typu abc. Kompilator będzie tego świadomy, gdy sprawdza poprawność semantyki, a ponieważ zna typ w czasie kompilacji, nie widzi w tym problemu.

W drugim przypadku (czas pracy) zostanie utworzona wartość, do której odniesienie będzie się odnosić. To tutaj może potencjalnie wpakować się w kłopoty. Na przykład, jeśli powiedział, co następuje:

public class abc { 
    private abc p; 

    public abc() { 
     p = new abc(); 
    } 
} 

Może to prowadzić do kłopotów z dokładnym powodu cytowanej (rekursji, że nie zawiera przypadkiem bazowym i będzie stale przydzielić pamięci, dopóki nie uruchomić maszynę wirtualną z hałdy przestrzeń).

Jednak nadal można zrobić coś podobnego i uniknąć nieskończonej rekursji. Unikając tworzenia wartości podczas budowy, odkładasz ją, dopóki nie zostanie wywołana metoda. W rzeczywistości jest to jeden z najczęstszych sposobów implementacji the singleton pattern w Javie. Na przykład:

public class abc { 
    private abc p; 

    private abc() { // Private construction. Use singleton method 
    } 

    public static synchronized abc getInstance() { 
     if (p == null) 
      p = new abc(); 

     return p; 
    } 
} 

Jest idealnie ważne, ponieważ utworzyć tylko jedną nową instancję wartości, a od czasu wykonywania zostanie załadowany klasa już będzie znać typ zmiennej instancji jest prawidłowy.

+3

Twoja odpowiedź naprawdę bardzo pomaga. Dzięki Doug. –

+0

Cieszę się, że mogę pomóc. –

0

Podczas gdy mówimy o "rekurencji", "wykonanie" kodu jest punktem, który rozważamy. Tak, jest "dynamiczny", jeśli występuje "rekursja".

W deklaracji typu zmienną, która zawiera element członkowski, który jest typem zmiennej zawierającej, jest "static". Na przykład pudełko może zawierać inne pudełko wewnątrz i tak dalej. Ale w końcu jest najmniejsze pudełko, które nie zawiera niczego. W przypadku łańcucha wagonów kolejowych każdy powóz ma członka do następnego przewozu z wyjątkiem ostatniego przewozu.

W programie dane statyczne muszą być "skończone" (nie masz "nieskończonej" przestrzeni pamięci). Wykonanie kodu może być "nieskończone". Ale jest wyjątek. Po prostu obrazuję krąg łańcucha.

0

Podsumowując niektóre z odpowiedzi tutaj.

Klasa zawiera odniesienie do jednego rodzaju. Najlepszą analogią w świecie rzeczywistym byłoby poszukiwanie skarbu. Miejsce Clue ma pewne dane i wskazówkę, która prowadzi do kolejnego miejsca, o którym powtarzasz.

Nie oznacza to, że miejsce z tropem ma w sobie inną wskazówkę, taką, o jakiej się domyślacie.

Powiązane problemy