Warum nicht eine statische Methode über eine Instanz einen Fehler für den Java-Compiler Aufruf?

StackOverflow https://stackoverflow.com/questions/610458

  •  03-07-2019
  •  | 
  •  

Frage

Ich bin sicher, dass Sie alle das Verhalten wissen, ich meine - Code wie:

Thread thread = new Thread();
int activeCount = thread.activeCount();

provoziert eine Compiler-Warnung. Warum ist es nicht ein Fehler?

EDIT:

Um klar zu sein: Frage hat nichts mit Themen zu tun. Mir ist klar, Gewinde Beispiele häufig gegeben werden, wenn dies wegen der möglichen Diskussion mit ihnen wirklich durcheinander zu bringen. Aber wirklich das Problem ist, dass eine solche Verwendung ist immer Unsinn und Sie können nicht (kompetent) schreiben einen solchen Anruf und meine es ernst. Jedes Beispiel für diese Art von Methodenaufruf wäre bekloppt. Hier ist eine andere:

String hello = "hello";
String number123AsString = hello.valueOf(123);

Was es wie aussehen läßt, wenn jede String-Instanz kommt mit einem "String valueOf (int i)" -Methode.

War es hilfreich?

Lösung

Im Grunde glaube ich, dass die Java-Designer einen Fehler gemacht, als sie die Sprache entwickelt, und es ist zu spät, um es zu beheben wegen der Kompatibilitätsproblemen beteiligt. Ja, es kann sehr irreführend Code führen. Ja, Sie sollten es vermeiden. Ja, sollten Sie Ihre IDE ist so konfiguriert, zu behandeln es als einen Fehler, IMO sicherstellen. Sollten Sie jemals eine Sprache entwickeln sie, tragen sie im Sinne, als ein Beispiel für die Art der Sache zu vermeiden:)

Nur um DJClayworth des Punkt zu antworten, hier ist was in C # erlaubt ist:

public class Foo
{
    public static void Bar()
    {
    }
}

public class Abc
{
    public void Test()
    {
        // Static methods in the same class and base classes
        // (and outer classes) are available, with no
        // qualification
        Def();

        // Static methods in other classes are available via
        // the class name
        Foo.Bar();

        Abc abc = new Abc();

        // This would *not* be legal. It being legal has no benefit,
        // and just allows misleading code
        // abc.Def();
    }

    public static void Def()
    {
    }
}

Warum denke ich, es ist irreführend? Denn wenn ich an Code someVariable.SomeMethod() aussehen erwarte ich es , um den Wert von someVariable . Wenn SomeMethod() eine statische Methode ist, ist, dass Erwartung ungültig; der Code trickst mich. Wie kann das möglicherweise sein ein gut , was?

Seltsam genug, Java lassen Sie nicht auf eine möglicherweise nicht initialisierten Variablen verwenden, um eine statische Methode zu nennen, trotz der Tatsache, dass die einzige Information, es ist der deklarierte Typ der Variablen zu verwenden, geht. Es ist ein inkonsistentes und nicht hilfreich Chaos. Warum es erlaubt?

EDIT: Diese Änderung ist eine Antwort auf Claytons Antwort, die es Vererbung für statische Methoden beansprucht werden kann. Es funktioniert nicht. Statische Methoden sind einfach nicht polymorph. Hier ist ein kurzes, aber vollständiges Programm zu zeigen, dass:

class Base
{
    static void foo()
    {
        System.out.println("Base.foo()");
    }
}

class Derived extends Base
{
    static void foo()
    {
        System.out.println("Derived.foo()");
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Base b = new Derived();
        b.foo(); // Prints "Base.foo()"
        b = null;
        b.foo(); // Still prints "Base.foo()"
    }
}

Wie Sie sehen können, wird der Ausführungszeitwert von b vollständig ignoriert.

Andere Tipps

Warum sollte es ein Fehler sein? Die Instanz hat Zugriff auf alle statischen Methoden. Die statischen Methoden nicht den Zustand der Instanz ändern können (versuchen zu ist ein Übersetzungsfehler).

Das Problem mit dem bekannten Beispiel, das Sie geben, ist sehr spezifisch für Themen , nicht statische Methode Anrufe. Es sieht aus, als ob Sie die activeCount() für den durch thread genannten Thread bekommen, aber du bist wirklich die Zählung für den anrufenden Thread zu bekommen. Dies ist ein logischer Fehler, den Sie als Programmierer machen. Abmahnung ist die richtige Sache für den Compiler in diesem Fall zu tun. Es liegt an Ihnen, um die Warnung zu beachten und den Code zu beheben.

EDIT: Ich stelle fest, dass die Syntax der Sprache ist, was erlaubt Sie schreiben Code irreführend, aber denken Sie daran, dass der Compiler und seine Warnungen Teil der Sprache sind es auch. Die Sprache ermöglicht es Ihnen, etwas zu tun, dass der Compiler fragwürdig hält, aber es gibt Ihnen die Warnung sicherstellen, dass Sie sich bewusst sind, dass es zu Problemen führen könnte.

Sie können es kein Fehler mehr machen, wegen all der Code, der bereits da draußen ist.

Ich bin mit Ihnen auf, dass es sollte ein Fehler sein. Vielleicht sollte es eine Option / profile sein, dass der Compiler einige Warnungen, um Fehler zu aktualisieren.

Update: Wenn sie führte die Assertion Stichwort in 1.4, die ähnlichen mögliche Kompatibilitätsprobleme mit altem Code hat, sie machte es

Kurze Antwort -. Die Sprache erlaubt es, so ist es kein Fehler

Wahrscheinlich für die gleichen logisch, dass diese nicht einen Fehler macht:

public class X
{
    public static void foo()
    {
    }

    public void bar()
    {
        foo(); // no need to do X.foo();
    }
}

Die wirklich wichtige Sache, aus der Perspektive des Compilers, ist, dass es in der Lage sein, Symbole zu lösen. Im Fall einer statischen Methode, muss er wissen, welche Klasse es suchen in - da sie nicht mit einem bestimmten Objekt zugeordnet ist. Java-Designer entschieden offensichtlich, dass, da sie die Klasse eines Objekts bestimmen konnte, sondern auch die Klasse eines statischen Methode für das Objekt von jeder Instanz des Objekts lösen könnte. Sie wählen, damit diese - schwankte, vielleicht durch @ TofuBeer Beobachtung - dem Programmierer eine gewisse Bequemlichkeit zu geben. Andere Sprach Designer haben unterschiedliche Entscheidungen getroffen. Mir wahrscheinlich in diesem Lager wäre gefallen, aber es ist nicht so große Sache für mich. Ich würde wahrscheinlich die Nutzung erlauben, die @TofuBeer erwähnt, aber es ist meine Position nicht den Zugang gestattet zu haben, von einer Instanz Variable weniger haltbar ist.

Es ist kein Fehler, weil es Teil der Spezifikation ist, aber du bist offensichtlich über die Gründe zu fragen, die wir alle zu erraten können.

Meine Vermutung ist, dass die Quelle dieser eigentlich eine Methode in einer Klasse zu ermöglichen, ist eine statische Methode in der gleichen Klasse ohne lästiges aufzurufen. Da Aufruf x () ist legal (auch ohne Selbstklassennamen), ruft this.x () sollte auch legalisiert wurde als gut, und deshalb fordern über jedes Objekt legal sein.

Dies hilft auch Benutzer sollen Anreize für private Funktionen in statisch machen, wenn sie nicht den Zustand ändern.

Außerdem Compiler der Regel versuchen, Fehler zu vermeiden, deklarieren, wenn es keine Möglichkeit gibt, dass dies zu einem direkten Fehler führen könnte. Da eine statische Methode oder kümmern sich um das aufrufende Objekt nicht den Zustand ändern, verursacht es keine tatsächlichen Fehler (knapp Verwirrung) Um dies zu ermöglichen. Eine Warnung genügt.

Der Zweck der Instanzvariable Referenz ist nur die Art zu liefern, das die statische umschließt. Wenn Sie auf Byte-Code suchen eine statische über instance.staticMethod oder EnclosingClass.staticMethod Aufruf erzeugt die gleiche invoke statische Methode Bytecode. Kein Verweis auf die Instanz angezeigt wird.

Die Antwort, wie auch, warum es da drin, gut es ist einfach so. Solange Sie die Klasse verwenden. und nicht über eine Instanz helfen Sie Verwirrung in der Zukunft zu vermeiden.

Wahrscheinlich können Sie es in Ihrem IDE ändern (in Eclipse Einstellungen -> Java -> Compiler -> Fehler / Warnungen)

Es gibt nicht Option für sie. In Java (wie viele andere lang.) Können Sie den Zugriff auf alle statischen Mitglieder einer Klasse durch seine Klassennamen oder Instanz Objekt dieser Klasse haben. Das bis zu Ihnen sein würde und Ihren Fall und Software-Lösung, die Sie verwenden sollten, dass gibt Ihnen mehr Lesbarkeit.

ich diese nur betrachten:

instanceVar.staticMethod();

für diese Kurzschrift werden:

instanceVar.getClass().staticMethod();

Wenn Sie immer hat, dies zu tun:

SomeClass.staticMethod();

dann würden Sie nicht in der Lage sein, die Vererbung für statische Methoden zu nutzen.

Das heißt, durch die statische Methode über die Instanz aufrufen Sie müssen nicht wissen, welche konkrete Klasse die Instanz bei der Kompilierung ist, nur dass es implementiert Static () irgendwo entlang der Vererbungskette.

EDIT: Diese Antwort ist falsch. Siehe Anmerkungen für Details.

scroll top