Mam klasę, która musi mieć pewne metody statyczne. Wewnątrz tych metod statycznych muszę wywołać metodę getClass (), aby wykonać następujące wywołanie:
public static void startMusic() {
URL songPath = getClass().getClassLoader().getResource("background.midi");
}
Jednak Eclipse mówi mi:
Cannot make a static reference to the non-static method getClass()
from the type Object
Jaki jest właściwy sposób naprawienia tego błędu czasu kompilacji?
java
static-methods
Rama
źródło
źródło
getResource()
przed wystąpieniem klasy zdefiniowanej przez użytkownika (np. Innej niż J2SE) czasami kończy się niepowodzeniem. Problem polega na tym, że środowisko JRE będzie używać modułu ładującego klasy bootstrap na tym etapie, który nie będzie miał zasobów aplikacji na ścieżce klasy (modułu ładującego bootstrap).Odpowiedzi:
Odpowiedź
Po prostu użyj
TheClassName.class
zamiastgetClass()
.Deklarowanie rejestratorów
Ponieważ jest to tak ważne dla konkretnego przypadku użycia - aby zapewnić łatwy sposób wstawiania deklaracji dziennika - pomyślałem, że dodam swoje przemyślenia na ten temat. Struktury dziennika często oczekują, że dziennik będzie ograniczony do określonego kontekstu, powiedzmy w pełni kwalifikowana nazwa klasy. Nie można ich więc wklejać bez modyfikacji. Sugestie dotyczące deklaracji dziennika bezpiecznych dla wklejania znajdują się w innych odpowiedziach, ale mają one wady, takie jak zawyżanie kodu bajtowego lub dodanie introspekcji środowiska wykonawczego. Nie polecam tych. Kopiuj-wklej jest kwestią edytora , więc rozwiązanie edytora jest najbardziej odpowiednie.
W IntelliJ polecam dodanie szablonu na żywo:
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class);
jako tekstu szablonu.className()
Teraz, jeśli wpiszesz
log<tab>
, automatycznie rozwinie się doI automatycznie sformatuj i zoptymalizuj importowanie.
źródło
Log
w Androidzie, które wymaga podania tagu, zwykle nazwy klasy. I są prawdopodobnie inne przykłady. Oczywiście możesz zadeklarować pole do tego (co jest powszechną praktyką), ale nadal jest to kopiowanie i wklejanie.CLASS
wpisaćclassName()
. To sprawi, że $ CLASS $ zostanie faktycznie zastąpione nazwą klasy, w przeciwnym razie będzie po prostu puste.Jeśli chodzi o przykład kodu w pytaniu, standardowym rozwiązaniem jest jawne odwołanie się do klasy poprzez jej nazwę, a nawet można obejść się bez
getClassLoader()
wywołania:To podejście wciąż ma drugą stronę, ponieważ nie jest bardzo bezpieczne przed błędami kopiowania / wklejania na wypadek, gdybyś musiał skopiować ten kod do wielu podobnych klas.
A jeśli chodzi o dokładne pytanie w nagłówku, w sąsiednim wątku jest podana sztuczka :
Używa zagnieżdżonej anonimowej
Object
podklasy, aby uzyskać kontekst wykonania. Zaletą tej sztuczki jest bezpieczeństwo kopiowania / wklejania ...Zachowaj ostrożność podczas używania tego w klasie bazowej, którą inne klasy dziedziczą:
Warto również zauważyć, że jeśli ten fragment kodu jest ukształtowany jako metoda statyczna jakiejś klasy bazowej, wówczas
currentClass
wartość zawsze będzie odnosić się do tej klasy bazowej, a nie do dowolnej podklasy, która może korzystać z tej metody.źródło
Class.getResource()
może zachowywać się nieco inaczejClassLoader.getResource()
; patrz stackoverflow.com/a/676273W Java7 + możesz to zrobić w statycznych metodach / polach:
źródło
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
Sam się z tym zmagałem. Fajną sztuczką jest użycie bieżącego wątku, aby uzyskać ClassLoader w kontekście statycznym. Będzie to działać również w Hadoop MapReduce. Inne metody działają podczas uruchamiania lokalnego, ale zwracają zerowy InputStream, gdy są używane w MapReduce.
źródło
Po prostu użyj literału klasowego, tj
NameOfClass.class
źródło
getClass()
Metoda jest zdefiniowana w klasie Object za pomocą następującego podpisu:Ponieważ nie jest zdefiniowany jako
static
, nie można wywoływać go w bloku kodu statycznego. Zobacz te odpowiedzi, aby uzyskać więcej informacji: Q1 , Q2 , Q3 .Jeśli jesteś w kontekście statycznym, musisz użyć dosłownego wyrażenia klasy, aby uzyskać klasę, więc w zasadzie musisz zrobić:
Ten typ wyrażenia nazywa się literałami klas i są one wyjaśnione w Księdze specyfikacji języka Java w następujący sposób:
Informacje na ten temat można również znaleźć w dokumentacji API dla Class.
źródło
Spróbuj
Lub
źródło
[1]
spowoduje, że wszystkie komunikaty dziennika będą zgłaszaneThread
jako źródło w Androidzie 4.4.4.[2]
wydaje się dawać poprawny wynik zarówno na Androidzie, jak i na OpenJRE.Załóżmy, że istnieje klasa Utility, a przykładowy kod to:
CustomLocation - jeśli jakakolwiek struktura folderów w obrębie zasobów w przeciwnym razie usunie ten literał ciągu.
źródło
Spróbuj czegoś takiego. Mi to pasuje. Logg (nazwa klasy)
źródło