static nested class

Odpowiedz Nowy wątek
2012-07-02 21:53

Rejestracja: 8 lat temu

Ostatnio: 4 lata temu

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"

edytowany 1x, ostatnio: Hell4Ge, 2012-07-02 21:55
To nie jest deklaracja statycznej klasy, ale statycznego pola. - Olamagato 2012-07-03 00:14

Pozostało 580 znaków

2012-07-02 22:19

Rejestracja: 14 lat temu

Ostatnio: 18 godzin temu

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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit, 2012-07-02 22:28

Pozostało 580 znaków

2012-07-02 23:10

Rejestracja: 14 lat temu

Ostatnio: 6 lat temu

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


pecet
edytowany 2x, ostatnio: pecet, 2012-07-02 23:14
W sumie jak dla mnie to to jest dość sztuczne ograniczenie. - Wibowit 2012-07-02 23:33

Pozostało 580 znaków

2012-07-03 01:07

Rejestracja: 11 lat temu

Ostatnio: 1 rok temu

Lokalizacja: Polska, Warszawa

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
        //...
    }
}

Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 4x, ostatnio: Olamagato, 2012-07-03 10:28
ale porąbane... - Azarien 2012-07-03 08:07

Pozostało 580 znaków

2012-07-03 11:29

Rejestracja: 14 lat temu

Ostatnio: 6 lat temu

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() {
        }
    }
}

pecet

Pozostało 580 znaków

2012-07-03 11:46

Rejestracja: 14 lat temu

Ostatnio: 18 godzin temu

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?).


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2012-07-03 14:25

Rejestracja: 14 lat temu

Ostatnio: 6 lat temu

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


pecet

Pozostało 580 znaków

2012-07-03 14:29

Rejestracja: 14 lat temu

Ostatnio: 18 godzin temu

0

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


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2012-07-03 14:42

Rejestracja: 11 lat temu

Ostatnio: 1 rok temu

Lokalizacja: Polska, Warszawa

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ć.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 2x, ostatnio: Olamagato, 2012-07-03 15:24

Pozostało 580 znaków

Odpowiedz

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