static nested class

0

Co nieco z C++ wiem, ale chcę przejść do Javy, i zacząłem od "Thinking in Java by Bruce Eckel"

Cudownie, doszedłem do tematu, gdzie autor przedstawia deklarację statycznych klas w taki sposób

 
class StaticTest {
static int i = 47;
}

Otóż to nie działa, korzystam z najnowszych JDK, i może książka była przeznaczona do wersji 6, a nie 7, to mimo wszystko taka rzecz nie powinna raczej ulec zmianie...

To samo pisze tu:
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Eclipse nałogowo nakazuje mi usuwanie static, i w przypadku kombinowania - wielu innych fragmentów kodu, które po komentarzach w sieci na pewno są dobre

Nie wiem, może Eclipse przerywa kompilacje przez warningi?

W każdym razie, jak deklarować zmienne statyczne w klasie osadzonej?

"The field i cannot be declared static in a non-static inner type, unless initialized with a constant expression"

0

Podaj kod który ci nie działa.

Edit:
Uściślając: podaj minimalny niekompilujący się kod, który obrazuje twój problem, a w którym do skompilowania wystarczy usunięcie modyfikatora static tak jak to Eclipse sugeruje.

0

tu chyba chodzi o coś takiego

 
public class A {

    class B{
        static int i = 5;
    }
}

modyfikator static jest niedozwolony w klasach wewnętrznych
ALE

 
public class A {

    static class B{
        static int i = 5;
    }
}

ponieważ klasa B jest w takim wypadku statyczna (zagnieżdżona)

Edit:
http://lambda.univ.rzeszow.pl/kb/java/inner/testy.htm

1

Przykład, który przytaczasz pochodzi ze strony 80 - przed rozdziałem "Twój pierwszy program w Javie", a klasy zagnieżdżone zaczynają się od strony 310.
Twój problem polega na tym, że zdefiniowanie klasy w klasie jest w C++ domyślnie klasą zagnieżdżoną, która nie ma nic wspólnego z klasą rodzica poza zasięgiem nazw. W Javie zdefiniowanie klasy w klasie daje klasę wewnętrzną - twór, który w C++ nie istnieje. Obiekt takiej klasy istnieje tylko wtedy kiedy istnieje obiekt klasy nadrzędnej, więc pola statyczne w takich klasach nie mogą istnieć za wyjątkiem zainicjowanych pól static final (np. static final String DEATH="Aaaaaa...."). Dlatego IDE każe Ci z takich pól wyrzucać modyfikator static. Alternatywnie możesz dać static final i inicjator, co zamknie plucie się IDE.
Aby zrobić z takiej klasy wewnętrznej klasę zagnieżdżoną, trzeba dodać modyfikator static. Jeżeli go dodasz, to z tworzeniem pól statycznych dowolnego rodzaju nie ma żadnego problemu.
Kiedy JVM ładuje klasę, to wszystkie elementy statyczne są opracowywane właśnie wtedy, natomiast niestatyczne dopiero podczas tworzenia obiektu klasy (załadowanej i już zarejestrowanej). Dlatego klasy wewnętrzne, które są niestatyczne nie mogą zawierać elementów statycznych bo te musiałyby istnieć zanim klasa wewnętrzna mogłaby zostać załadowana.
To co pisze na tej stronie o dostępie do pól i metod statycznych jest trochę nieaktualne. Otóż dostęp do tych elementów przez obiekt, czyli egzemplarz klasy jest już niezalecany i jest w IDE traktowany jako ostrzeżenie. Obecnie z wszystkich elementów statycznych korzysta się wyłącznie poprzez nazwę klasy, w której są zawarte. A więc

public class External
{
	private class Internal
	{
		private static final CONST = 5;
	}
	//...
	private static class Nested
	{
		private static int CONST; //to nie jest prawdziwa stała, lecz zmienna "klasowa"
		//...
		CONST = 42;
		//...
		
	}
	//...
	private Internal internal = new Internal(); //pole niestatyczne
	private static Internal INTERNAL = new Internal(); //error
	private Nested nested = new Nested(); //pole niestatyczne
	private static Nested NESTED = new Nested(); //pole statyczne
	//...
	{
		//...
		int a = Nested.CONST; //dobrze
		int b = new Nested().CONST; //warning
		int c = new External().internal.CONST; //dobrze
		Nested d = External.NESTED; //dobrze
		int e = External.NESTED.CONST; //dobrze
		//...
	}
}
0

to powinno zobrazować różnice i zalety stosowanie tych rodzajów

 
import java.util.LinkedList;
import java.util.List;

public class ClassExternal<V1 extends ClassExternal.Internal, V2 extends ClassExternal.Nested> {//genetyczne

    private int i = 5;
    private static int k = 5;
    private List<Internal> internals = new LinkedList<>();//powiązanie 1 instancja klasy zewnętrznej = wiele instancji klas wewnętrznych
    private List<Nested> nesteds = new LinkedList<>();

    public ClassExternal() {
        internals.add(new Internal());
        internals.add(new Internal());
        nesteds.add(new Nested(this));
        nesteds.add(new Nested(this));
    }

    public static void main(String[] args) {
        //Klasa
        ClassExternal ce = new ClassExternal();
        //Interfejs
        InterfaceExternal ie = new InterfaceExternal() {
        };
        //klasa zagnieżdżona (statyczna)
        //może istnieć niezależnie od klasy zewnętrznej
        ClassExternal.Nested cen = new ClassExternal.Nested(ce);
        InterfaceExternal.Nested ien = new InterfaceExternal.Nested(ie);
        
        //nieistnieje bez klasy zewnętrznej
        //InterfaceExternal.Internal iei = new InterfaceExternal.Internal();
    }

    public <T extends Internal> T getInternal(Class<T> clazz) {
        return (T) new Internal();
    }

    public <T extends Nested> T getNested(Class<T> clazz) {
        return (T) new Nested(this);
    }

    public Internal getInternal2() {
        return new Internal();
    }

    public Nested getNested2() {
        return new Nested(this);
    }

    //możliwość tworzenia w metodach statycznych
    public static <T extends Nested> T getStaticNested(Class<T> clazz, ClassExternal external) {
        return (T) new Nested(external);
    }

    public static Nested getStaticNested(ClassExternal external) {
        return new Nested(external);
    }

    private void prywatna() {
    }
    
    private static void prywatna2() {
    }

    void external() {
        Internal i = internals.get(0);
        Nested n = nesteds.get(0);

        //dostęp do zmiennych prywatnych/chronionych      
        i.i = 6;
        n.i = 6;//ale brak do statycznych

        //dostęp do metod prywatnych/chronionych  
        i.prywatna();
        n.prywatna();
    }

    public class Internal {

        private int i = 5;

        public Internal() {
        }

        private void prywatna() {
        }

        void external() {
            //dostęp do zmiennych prywatnych/chronionych
            ClassExternal.this.i = 6;//powiązanie 1 instancja klasy zewnętrznej = wiele instancji klas wewnętrznych
            ClassExternal.k = 6;

            //dostęp do metod prywatnych/chronionych 
            ClassExternal.this.prywatna();
            ClassExternal.prywatna2();
        }
    }

    public static class Nested {

        private static int k = 5;
        private int i = 5;
        private ClassExternal external;

        public Nested(ClassExternal external) {
            this.external = external;
        }

        private void prywatna() {
        }

        void external() {
            //dostęp do zmiennych prywatnych/chronionych
            external.i = 6;//tylko przez konkretny obiekt
            ClassExternal.k = 6;

            //dostęp do metod prywatnych/chronionych 
            external.prywatna();
            ClassExternal.prywatna2();
        }
    }
}
public interface InterfaceExternal {

    //możliwość tworzenia w interfejsach
    //wszystkie klasy są statyczne
    class Nested {

        static int i = 5;
        InterfaceExternal external;

        public Nested(InterfaceExternal external) {
            this.external = external;
        }

        void external() {
        }
    }
}

0

Dlatego klasy wewnętrzne, które są niestatyczne nie mogą zawierać elementów statycznych bo te musiałyby istnieć zanim klasa wewnętrzna mogłaby zostać załadowana.

Nie rozumiem tego zdania. Z twojego wywodu wynika, że dodanie final do statica w klasie wewnętrznej powoduje, że kompilacja się powodzi. Czemu akurat final ratuje sprawę?

Moim zdaniem jest to dość sztuczne ograniczenie, no chyba, że ułatwia to pisanie JVMa (tylko znowu pytanie, dlaczego?).

0

modyfikator

  • static - oznacza że zmienna jest globalna w danej przestrzeni klasy
  • final - oznacza że zmienna jest stałą

połączenie static i final tworzy stałą globalną w danej przestrzeni klasy

0

Ameryki nie odkryłeś, ani na moje pytanie nie odpowiedziałeś.

0

@Wibovit
Modyfikator final ratuje sprawę ponieważ zmienna staje się stałą wbitą do bytecodu. Jest to wtedy taka sama wartość w kodzie jak stała 5 czy 'a' - tyle, że nazwana. Klasa wewnętrzna jest jakby "podwłasnością" zewnętrznej, ale jest tak implementowana, że jej pola i metody istnieją tak naprawdę na poziomie klasy zewnętrznej aby mogły mieć pełny dostęp do wszystkich jej pól i metod. Gdyby klasy wewnętrzne zaimplementowano tak jak klasy zagnieżdżone (statyczne), to wtedy nie mogłyby mieć (niejawnego) dostępu do wszystkich pól i metod klasy zewnętrznej. Z drugiej strony ponieważ może istnieć tylko jeden blok statyczny dla każdej klasy na poziomie zewnętrznym, więc klasy wewnętrzne nie mogą mieć takiego bloku - i tu leży powód dlaczego nie mogą mieć komponentów statycznych. W czasie projektowania był to pewnie wybór "coś za coś". Jednak ponieważ klasy zagnieżdżone również istnieją, to nie jest to bardzo bolesne bo ma się wybór czy klasa niższego poziomu ma mieć takie własności oraz ograniczenia czy ich nie mieć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1