423 Stimmen

Wie ruft man getClass() aus einer statischen Methode in Java auf?

Ich habe eine Klasse, die einige statische Methoden haben muss. Innerhalb dieser statischen Methoden muss ich die Methode getClass() aufrufen, um den folgenden Aufruf zu machen:

public static void startMusic() {
  URL songPath = getClass().getClassLoader().getResource("background.midi");
}

Allerdings sagt mir Eclipse:

Cannot make a static reference to the non-static method getClass() 
from the type Object

Wie lässt sich dieser Kompilierzeitfehler beheben?

717voto

Mark Peters Punkte 78448

Die Antwort

Verwenden Sie einfach TheClassName.class 代わりに getClass() .

Logger deklarieren

Da dies so viel Aufmerksamkeit für einen bestimmten Anwendungsfall erhält - um eine einfache Möglichkeit zum Einfügen von Protokollerklärungen zu bieten -, dachte ich, ich würde meine Gedanken dazu hinzufügen. Log-Frameworks erwarten oft, dass das Log auf einen bestimmten Kontext beschränkt ist, z.B. einen vollqualifizierten Klassennamen. Sie lassen sich also nicht ohne Änderungen kopieren und einfügen. Vorschläge für einfügungssichere Protokolldeklarationen werden in anderen Antworten gegeben, aber sie haben Nachteile wie das Aufblähen von Bytecode oder das Hinzufügen von Introspektion zur Laufzeit. Ich empfehle diese nicht. Kopieren-Einfügen ist eine Herausgeber daher ist eine Editorlösung am besten geeignet.

In IntelliJ empfehle ich, eine Live-Vorlage hinzuzufügen:

  • Verwenden Sie "log" als Abkürzung
  • Utilice private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class); als Text der Vorlage.
  • Klicken Sie auf Variablen bearbeiten und fügen Sie CLASS mit dem Ausdruck className()
  • Aktivieren Sie die Kästchen, um FQ-Namen neu zu formatieren und zu kürzen.
  • Ändern Sie den Kontext in Java: Deklaration.

Wenn Sie nun Folgendes eingeben log<tab> wird es automatisch erweitert auf

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

Und die Importe werden automatisch für Sie neu formatiert und optimiert.

135voto

Sergey Ushakov Punkte 2309

Was das Codebeispiel in der Frage betrifft, so besteht die Standardlösung darin, die Klasse explizit über ihren Namen zu referenzieren, und es ist sogar möglich, ohne getClassLoader() anrufen:

class MyClass {
  public static void startMusic() {
    URL songPath = MyClass.class.getResource("background.midi");
  }
}

Dieser Ansatz hat jedoch den Nachteil, dass er nicht sehr sicher gegen Copy/Paste-Fehler ist, falls Sie diesen Code in eine Reihe ähnlicher Klassen replizieren müssen.

Und was die genaue Frage in der Überschrift angeht, so gibt es einen Trick, der in der angrenzendes Gewinde :

Class currentClass = new Object() { }.getClass().getEnclosingClass();

Sie verwendet eine verschachtelte anonyme Object Unterklasse, um an den Ausführungskontext zu gelangen. Dieser Trick hat den Vorteil, dass er kopier- und einfügungssicher ist...

Vorsicht bei der Verwendung dieser Funktion in einer Basisklasse, von der andere Klassen erben:

Es ist auch erwähnenswert, dass, wenn dieses Snippet als statische Methode einer Basisklasse geformt ist, dann currentClass Wert ist immer ein Verweis auf diese Basisklasse und nicht auf eine Unterklasse, die diese Methode möglicherweise verwendet.

89voto

Rein Punkte 2347

In Java7+ können Sie dies in statischen Methoden/Feldern tun:

MethodHandles.lookup().lookupClass()

27voto

starkadder Punkte 301

Ich habe selbst mit dieser Frage gerungen. Ein netter Trick ist es, den aktuellen Thread zu verwenden, um einen ClassLoader in einem statischen Kontext zu erhalten. Dies wird auch in einem Hadoop MapReduce funktionieren. Andere Methoden funktionieren, wenn sie lokal ausgeführt werden, geben aber einen null InputStream zurück, wenn sie in einem MapReduce verwendet werden.

public static InputStream getResource(String resource) throws Exception {
   ClassLoader cl = Thread.currentThread().getContextClassLoader();
   InputStream is = cl.getResourceAsStream(resource);
   return is;
}

16voto

Michael Borgwardt Punkte 334642

Verwenden Sie einfach ein Klassenliteral, d. h. NameOfClass.class

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