2012-05-20 5 views
5

Próbuję zaimplementować połączoną kolekcję przy użyciu generycznych elementów, takich jak poniższe.Błąd kompilacji generycznego tworzenia szyny z klasy wewnętrznej

public class A<E> { 

    private class B { 

    private B[] b; 
    private E item; 

    private B() { 
     this.b = new B[2]; 
    } 

    } // end inner class B 

} // end class A 

A to kolekcja i B element lub węzeł w kolekcji z tablicą zawierającą następniki/poprzedniki i element.

Tworzenie tablicy jest niedozwolone. Otrzymuję błąd: generic array creation. Czy mam rację, gdy myślę, że to, co tworzy, to tablica A<E>.B?

Jeśli nie, co powoduje błąd?

Jeśli tak, jak mogę to obejść?

Oczywiście pominięto znaczną ilość kodu, jeśli to, co podałem, nie wystarczy, proszę dać mi znać. Każda rada byłaby doceniona. Dziękuję Ci.

EDIT 1: Powinienem wspomnieć, że sparametryzowany typ musi być taki sam w A jak w B. Przekazywanie <E> do klasy wewnętrznej nie jest możliwe, ponieważ tworzy E#2 i pozostawia A z E#1.

+0

Nie specjalnie odpowiedź na swoje pytanie, ale byłoby lepiej konstrukcja mieć dwie zmienne " poprzednik "i" następca "typu B zamiast zestawu dwóch elementów. Czyni twoją klasę łatwiejszą do przeczytania. Sądzę, że to by sprawiło, że twój problem zniknął? –

+0

WRT Edit1, wypróbuj 'statyczną klasę B ' i nie będziesz mieć problemu z nazewnictwem. Tablica nadal nie będzie działać, ponieważ jest generyczna. –

+0

Można również obejść ten problem, używając ogólnej kolekcji zamiast tablicy. – trutheality

Odpowiedz

4

zadzwonić B dziedziczy rodzajową z zewnętrznej klasy, ponieważ nie jest statyczny. I nie możesz po prostu zrobić tego statycznie, ponieważ będzie wtedy potrzebował także E.

Więc tablica B.b rzeczywiście potrzebują typ, który jest ogólna, tj A<E>.B lub jeśli chcesz zmienić swój kod do statyczny wewnętrznej klasy, A.B<E> (jeśli byłoby użyć private static class B<E>).

W języku Java, ze względu na sposób implementacji generics (przez wymazanie), typ tablicy nie jest dobrze zdefiniowany. Z jednej strony powinien to być układ B, z drugiej strony powinien to być układ Object.

Najbardziej praktycznym rozwiązaniem wydaje się używanie Object[] i wyraźne rzutowanie. Jeśli chcesz zwiększyć bezpieczeństwo typu, możesz oczywiście użyć narzędzia ArrayList<B>, które wewnętrznie używa także Object[]!

W konkretnym kodzie, B b1, b2; może być również opcją, która jest rzeczywiście szybsza (bez sprawdzania granic) i wymaga mniej pamięci (brak obiektu tablicy, brak informacji o rozmiarze).

+0

Myślałem o użyciu oddzielnych odniesień b1, b2. Wygląda na to, że jest to najbardziej odpowiedni sposób. To po prostu powoduje bardziej skomplikowane przejście kolekcji w niektórych metodach. Dziękuję za opinię, bardzo pomocne. – comfortablejohn

-2

Trzeba zdać E do wewnętrznej klasy także

private class B<E> { 

      private B[] b; 
      private E item; 

      private B() { 
       this.b = new B[2]; 
      } 

     } // end inner class B 
+2

Czy to nie spowoduje tego samego błędu? –

+0

Tak. Zgodnie z moją edycją wymagam, aby typy były takie same zarówno w klasie zewnętrznej, jak i wewnętrznej. Wykonanie powyższego oznaczać będzie, że chociaż obaj mogą być obróceni w ten sam typ, powiedzmy, że "A " powoduje, że są one zarówno liczbami całkowitymi, ale nie są porównywalne lub kompatybilne podczas odwoływania się między nimi. – comfortablejohn

+0

Niestety, nie widzę żadnej korzyści. W twojej konfiguracji powinno to być IMHO tak naprawdę "prywatna klasa statyczna B ", aby nie nadwerężyć nazwy i nadal nie pozwoli na utworzenie tablicy "nowe B [2]". –

2

B to niestatyczna klasa wewnętrzna. Oznacza to, że ma odniesienie do instancji klasy otaczającej. Jest więc domyślnie sparametryzowana przez parametr typu zewnętrznej klasy. Więc kiedy piszesz B, oznacza to A<E>.B. Aby utworzyć tablicę, powinieneś użyć klasy raw.Jednak B nie jest klasą surową; odnieść się do surowego klasy trzeba jednoznacznie zakwalifikować go: A.B

Tak to jest, że chcesz:

this.b = new A.B[2]; 
Powiązane problemy