[java] 비 정적 메서드에 대한 정적 참조를 만들 수 없습니다.

자바로 다국어 애플리케이션 구축. R.string리소스 XML 파일 에서 문자열 값을 삽입 할 때 오류가 발생 합니다.

public static final String TTT =  (String) getText(R.string.TTT);

다음은 오류 메시지입니다.

오류 : Context 유형에서 비 정적 메서드 getText (int)에 대한 정적 참조를 만들 수 없습니다.

이 문제는 어떻게 발생하며 어떻게 해결할 수 있습니까?



답변

이후 getText() 비 정적 인 당신은 정적 메서드에서 호출 할 수 없습니다.

그 이유를 이해하려면 둘의 차이점을 이해해야합니다.

인스턴스 (비 정적) 메서드는 특정 유형 (클래스)의 객체에서 작동합니다. 이것들은 다음과 같이 새로 만들어집니다.

SomeClass myObject = new SomeClass();

인스턴스 메서드를 호출하려면 인스턴스 ( myObject) 에서 호출합니다 .

myObject.getText(...)

그러나 정적 메서드 / 필드는 다음 과 같이 형식에 대해서만 직접 호출 할 수 있습니다
. 이전 문이 올바르지 않습니다. 같은 객체 참조를 사용하여 정적 필드를 참조 할 수도 myObject.staticMethod() 있지만 클래스 변수임을 명확하게하지 않기 때문에 권장되지 않습니다.

... = SomeClass.final

그리고 둘은 서로 다른 데이터 공간 (인스턴스 데이터 및 클래스 데이터)에서 작동하므로 함께 작동 할 수 없습니다.

제가 시도하고 설명하겠습니다. 이 클래스를 고려하십시오 (psuedocode) :

class Test {
     string somedata = "99";
     string getText() { return somedata; }
     static string TTT = "0";
}

이제 다음과 같은 사용 사례가 있습니다.

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

가치는 무엇입니까?

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

즉, TTT은 유형의 모든 인스턴스에서 공유하는 기준입니다. 그래서 말이 안돼

class Test {
         string somedata = "99";
         string getText() { return somedata; }
  static string TTT = getText(); // error there is is no somedata at this point 
}

그래서 질문은 왜 TTT가 정적이거나 왜 getText ()가 정적이 아닌가?

를 제거하면 static이 오류를지나 쳐야합니다.하지만 유형이 무엇인지 이해하지 못하면 다음 오류가 발생할 때까지 고착 석고 일뿐입니다. getText()비 정적이어야 하는 요구 사항은 무엇입니까 ?


답변

비 정적 Context방법 의 혼합을 getText()사용할 수없는 이유에 대한 설명과 함께 이미 좋은 답변 이 있습니다.static final String .

물어볼 좋은 질문은 다음과 같습니다.이 작업을 수행하려는 이유는 무엇입니까? 리소스 String에서 를로드하고 strings해당 값을 public static필드에 채우려 고 합니다. 나는 이것이 당신의 다른 클래스 중 일부가 액세스 할 수 있도록하는 것이라고 생각합니까? 그렇다면이 작업을 수행 할 필요가 없습니다. 대신 Context다른 클래스 에을 전달하고 그 context.getText(R.string.TTT)안에서 호출하십시오 .

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

그리고 이것을 당신에게서 부르려면 Activity:

NonActivity.doStuff(this);

이렇게하면 필드 String를 사용하지 않고도 리소스 에 액세스 할 수 있습니다 public static.


답변

검색에서 이것을 찾은 다른 사람들을 위해 :

나는 실수로 객체 이름이 아닌 클래스 이름을 사용하여 함수를 호출 할 때 종종 이것을 얻습니다. 이것은 일반적으로 너무 비슷한 이름을 제공하기 때문에 발생합니다 .P

즉 :

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

이것은 분명히 정적 방법입니다. (뭔가에 좋다)하지만 내가 정말로하고 싶었던 것은 (대부분의 경우)

myclass.someFunction();

정말 어리석은 실수이지만, 몇 달에 한 번씩 “MyClass”정의에서 vars를 엉망으로 만드는 데 약 30 분을 허비하여 실제로 오타 일 때 잘못하고있는 일을 해결합니다.

재미있는 참고 사항 : 스택 오버플로는 여기서 실수를 분명하게 만드는 구문을 강조합니다.


답변

변수를 비 정적으로 만들 수 있습니다.

public final String TTT =  (String) getText(R.string.TTT);

또는 “getText”메서드를 정적으로 만듭니다 (가능한 경우).


답변

getText는 활동의 구성원이므로 “this”가있을 때 호출해야합니다. 활동이 생성되기 전에 클래스가로드되면 정적 변수가 초기화됩니다.

리소스 문자열에서 변수를 초기화하기를 원하므로 정적 일 수 없습니다. 정적으로 만들려면 String 값으로 초기화 할 수 있습니다.


답변

비 정적 메서드에서는 정적 변수를 참조 할 수 없습니다. 이를 이해하려면 정적과 비 정적의 차이점을 이해해야합니다.

정적 변수는 클래스 변수이며 처음에만 생성 된 인스턴스가 하나 뿐인 클래스에 속합니다. 비 정적 변수는 클래스의 객체를 만들 때마다 초기화됩니다.

이제 질문에 도달하면 new () 연산자를 사용할 때 모든 객체에 대해 모든 비 정적 파일의 복사본을 만들지 만 정적 필드의 경우는 그렇지 않습니다. 그렇기 때문에 비 정적 메서드에서 정적 변수를 참조하는 경우 컴파일 시간 오류가 발생합니다.


답변

이 질문은 새로운 것이 아니며 기존 답변은 좋은 이론적 배경을 제공합니다. 좀 더 실용적인 답변을 추가하고 싶습니다.

getText는 Context 추상 클래스의 메서드이며이를 호출하려면 하위 클래스 (Activity, Service, Application 또는 기타)의 인스턴스가 필요합니다. 문제는 Context 인스턴스가 생성되기 전에 공개 정적 최종 변수가 초기화된다는 것입니다.

이 문제를 해결하는 방법에는 여러 가지가 있습니다.

  1. 정적 수정자를 제거하고 클래스 본문 내에 배치하여 변수를 Activity 또는 Context의 다른 하위 클래스의 멤버 변수 (필드)로 만듭니다.
  2. 정적으로 유지하고 초기화를 나중에 (예 : onCreate 메서드에서) 지연시킵니다.
  3. 실제 사용 대신 지역 변수로 만드십시오.