20 Stimmen

Es kann kein statischer Verweis auf das nicht-statische Feld memberVariable mit privater Variable erstellt werden

Ich habe eine Aufzählung mit einer privaten Mitgliedsvariablen erstellt. Wenn ich versuche, auf die Member-Variable zuzugreifen, wird kompiliert: "Cannot make a static reference to the non-static field memberVariable".

Wenn die Variable nicht privat ist (z. B. protected oder package protected), wird sie problemlos kompiliert. Ich verstehe nicht, was der Geltungsbereich der Variablen mit dem Typ (statisch, nicht statisch) der implementierten abstrakten Funktion zu tun hat.

Kann mich jemand aufklären?

public enum EnumWithAbstractMethodAndMembers {
    TheOneAndOnly(1) {
        @Override
        public int addValue(final int value) {
            return memberVariable + value;
        }
    };

    private final int memberVariable;

    private EnumWithAbstractMethodAndMembers(final int memberVariable) {
        this.memberVariable = memberVariable;
    }

    abstract int addValue(int value);

}

22voto

Peter Lawrey Punkte 511323

Die Fehlermeldung ist verwirrend.

Das Problem ist, dass Sie eine anonyme Unterklasse der Aufzählung erstellen, wenn Sie einen Aufzählungswert codieren. (Ihre Klasse wird EnumWithAbstractMethodAndMembers$1 ) Eine Unterklasse kann nicht auf die privaten Mitglieder ihrer Oberklasse zugreifen, verschachtelte Klassen können dies jedoch über eine generierte Accessor-Methode. Sie sollten in der Lage sein, auf das private Feld zuzugreifen, und die Fehlermeldung, die Sie erhalten, scheint irreführend zu sein.

BTW Sie können dies verwenden, aber Sie sollten es IMHO nicht brauchen.

    public int addValue(final int value) {
        return super.memberVariable + value;
    }

Hier ist ein kürzeres Beispiel, das ich als Fehler in der Fehlermeldung protokollieren werde, da es nicht zu einer Lösung des Problems führt.

public enum MyEnum {
    One {
        public int getMemberVariableFailes() {
            // error: non-static variable memberVariable cannot be referenced from a static context
            return memberVariable;
        }

        public int getMemberVariable2OK() {
            return memberVariable2;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    };

    private final int memberVariable = 1;
    final int memberVariable2 = 1;
}

Aufgrund der Rückmeldung von Tom Hawkin erhält dieses Beispiel die gleiche Fehlermeldung.

public class MyNotEnum {
    // this is the static context in which the anonymous is created
    public static final MyNotEnum One = new MyNotEnum() {
        public int getMemberVariableFailes() {
            // error: non-static variable memberVariable cannot be referenced from a static context
            return memberVariable;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    };
    private final int memberVariable = 1;
}

zum Vergleich

public class MyNotEnum {
    public class NestedNotEnum extends MyNotEnum {
        public int getMemberVariableFailes() {
            // compiles just fine.
            return memberVariable;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    }
    private final int memberVariable = 1;
}

4voto

Tom Hawtin - tackline Punkte 142461

Ein ähnliches Thema wird in Puzzle 92 (Twisted Pair) behandelt Java-Rätsel von Josh Bloch und Neal Gafter.

Es ist nichts Besonderes an Enums. Jede anonyme (oder lokale) innere Klasse in einem statischen Kontext ist geeignet. Die Regeln besagen, dass die äußere Klasse vor der Superklasse betrachtet wird. Dies ist für solche Klassen in einem nicht-statischen Kontext sehr sinnvoll. Wenn sich durch die Änderung des Kontexts zu statisch ändert, welche Variable nachgeschlagen wird, besteht die Möglichkeit, dass zur Laufzeit "Verwirrung" entsteht (C++ ist bei dieser Art von Regel viel aggressiver).

Eine innere Klasse, die eine äußere Klasse erweitert, hat Zugriff auf die privaten Instanzfelder der äußeren Klasse, entweder durch this oder eine andere Instanz.

Da uns der Zugang gestattet ist, müssen wir irgendwie angeben, dass wir durch das innere this und nicht durch das äußere this gehen wollen. Wie Peter Lawrey hervorhebt super.member genügt. Sie können auch das innere Dies auswählen und dann diesen Ausdruck verwenden:

        return ((EnumWithAbstractMethodAndMembers)this).memberVariable + value;

Oder

        EnumWithAbstractMethodAndMembers innerThis = this;
        return innerThis.memberVariable + value;

0voto

gtiwari333 Punkte 23343

Die Hauptfehlerursache ist : Sie versuchen, eine Referenz auf eine private Variable ( memberVariable ) der Oberklasse von der inneren Implementierungsklasse.

Um fehlerfreien Code zu erstellen, können Sie eine der folgenden Möglichkeiten nutzen:

  • müssen Sie super.memberVariable seit memberVariable es nicht lokal a TheOnlyAndOnly()
  • können Sie int memberVariable öffentlich .
  • können Sie tun:

    TheOneAndOnly(1) {
        int memberVariable=4;
        @Override
        public int addValue(final int value) {
            return memberVariable + value;
        }
    };

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X