[java] Java의 정적 메소드에서 getClass ()를 호출하는 방법은 무엇입니까?

정적 메소드가 있어야하는 클래스가 있습니다. 이 정적 메소드 내에서 getClass () 메소드를 호출하여 다음 호출을 수행해야합니다.

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

그러나 이클립스는 나에게 말한다 :

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

이 컴파일 시간 오류를 해결하는 적절한 방법은 무엇입니까?



답변

대답

TheClassName.class대신에 사용하십시오 getClass().

로거 선언

로그 선언을 쉽게 삽입 할 수 있도록 특정 유스 케이스에 많은 관심을 기울이기 때문에 그것에 대한 생각을 추가 할 것이라고 생각했습니다. 로그 프레임 워크는 종종 로그가 특정 컨텍스트 (예 : 정규화 된 클래스 이름)로 제한 될 것으로 예상합니다. 따라서 수정없이 복사 할 수 없습니다. 페이스트 안전 로그 선언에 대한 제안은 다른 답변에서 제공되지만 바이트 코드 팽창 또는 런타임 내부 검사 추가와 같은 단점이 있습니다. 나는 이것을 권장하지 않습니다. 복사-붙여 넣기는 편집자 문제이므로 편집기 솔루션이 가장 적합합니다.

IntelliJ에서는 라이브 템플릿을 추가하는 것이 좋습니다.

  • 약어로 “로그”를 사용하십시오.
  • private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class);템플릿 텍스트로 사용하십시오 .
  • 변수 편집을 클릭하고 표현식을 사용하여 클래스를 추가하십시오. className()
  • FQ 이름을 다시 포맷하고 줄이려면 확인란을 선택하십시오.
  • 컨텍스트를 Java : 선언으로 변경하십시오.

입력 log<tab>하면 자동으로 확장됩니다.

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

가져 오기를 자동으로 다시 포맷하고 최적화합니다.


답변

질문의 코드 예제와 관련하여 표준 솔루션은 클래스를 이름으로 명시 적으로 참조하는 것이며 getClassLoader()호출 하지 않고 수행 할 수도 있습니다 .

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

이 방법은 여전히 ​​뒷면에 코드를 복사하여 붙여 넣기 오류에 대해 안전하지 않다는 단점이 있습니다.이 코드를 여러 유사한 클래스에 복제해야하는 경우입니다.

헤드 라인의 정확한 질문에 대해서는 인접한 스레드에 게시 된 트릭이 있습니다 .

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

중첩 된 익명 Object서브 클래스를 사용 하여 실행 컨텍스트를 보유합니다. 이 트릭은 복사 / 붙여 넣기 안전이라는 이점이 있습니다 …

다른 클래스가 상속하는 기본 클래스에서 이것을 사용할 때주의하십시오.

또한이 스 니펫이 일부 기본 클래스의 정적 메소드로 구성 currentClass되면 값은 해당 메소드를 사용하는 서브 클래스가 아니라 항상 해당 기본 클래스에 대한 참조가됩니다.


답변

Java7 +에서는 정적 메소드 / 필드에서이를 수행 할 수 있습니다.

MethodHandles.lookup().lookupClass()


답변

나는 이것과 직접 씨름했다. 좋은 트릭은 정적 컨텍스트에서 현재 스레드를 사용하여 ClassLoader를 얻는 것입니다. 이것은 Hadoop MapReduce에서도 작동합니다. 다른 메소드는 로컬에서 실행될 때 작동하지만 MapReduce에서 사용될 경우 널 InputStream을 리턴합니다.

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


답변

간단히 클래스 리터럴을 사용하십시오. NameOfClass.class


답변

getClass() 메소드는 다음 서명을 사용하여 Object 클래스에 정의됩니다.

공개 최종 클래스 getClass ()

로 정의되어 static있지 않으므로 정적 코드 블록 내에서 호출 할 수 없습니다. 자세한 내용은 다음 답변을 참조하십시오 : Q1 , Q2 , Q3 .

정적 컨텍스트에 있다면 클래스 리터럴 표현식을 사용하여 클래스를 가져와야하므로 기본적으로 다음과 같이해야합니다.

푸 클래스

이 유형의 표현식을 클래스 리터럴 이라고 하며 Java 언어 사양서에 다음과 같이 설명되어 있습니다.

클래스 리터럴은 클래스 이름, 인터페이스, 배열 또는 기본 유형과`. ‘로 구성된 표현식입니다. 그리고 토큰 클래스. 클래스 리터럴의 유형은 클래스입니다. 현재 인스턴스 클래스의 정의 클래스 로더에 의해 정의 된 이름 지정된 유형 (또는 void)에 대해 Class 오브젝트로 평가됩니다.

이 주제에 대한 정보는 클래스의 API 문서 에서 찾을 수도 있습니다 .


답변

시도 해봐

Thread.currentThread().getStackTrace()[1].getClassName()

또는

Thread.currentThread().getStackTrace()[2].getClassName()