development

"정적 컨텍스트에서 비 정적 메소드를 참조 할 수 없음"의 이유는 무엇입니까?

big-blog 2020. 4. 6. 08:09
반응형

"정적 컨텍스트에서 비 정적 메소드를 참조 할 수 없음"의 이유는 무엇입니까? [복제]


이 질문에는 이미 답변이 있습니다.

가장 일반적인 초보자 실수는 해당 클래스의 인스턴스를 만들지 않고 클래스 속성을 "정적으로"사용하려고 할 때입니다. 언급 된 오류 메시지가 남습니다.

정적이 아닌 메소드를 정적으로 만들거나 해당 클래스의 인스턴스가 해당 속성을 사용하도록 할 수 있습니다.

왜? 나는 해결책을 요구하지 않습니다. 그 이유가 무엇인지 알게되어 기쁩니다. 핵심 이유!

private java.util.List<String> someMethod(){
    /* Some Code */
    return someList;            
}

public static void main(String[] strArgs){          
     // The following statement causes the error. You know why..
    java.util.List<String> someList = someMethod();         
}

존재하지 않는 것을 호출 할 수 없습니다. 객체를 만들지 않았으므로 비 정적 메서드는 아직 존재하지 않습니다. 정적 방법 (정의상)은 항상 존재합니다.


호출하려는 메소드는 인스턴스 레벨 메소드입니다. 인스턴스가 없습니다.

static메소드는 클래스에 static속하고 메소드는 클래스의 인스턴스에 속합니다.


객체 지향 프로그래밍의 본질은 작동하는 데이터와 함께 로직을 캡슐화하는 것입니다.

인스턴스 메소드는 논리이고 인스턴스 필드는 데이터입니다. 그들은 함께 사물을 형성합니다.

public class Foo
{
    private String foo;
    public Foo(String foo){ this.foo = foo; }
    public getFoo(){ return this.foo; }

    public static void main(String[] args){
        System.out.println( getFoo() );
    }
}

위 프로그램을 실행 한 결과는 무엇입니까?

객체가 없으면 인스턴스 데이터가 없으며 인스턴스 메소드가 클래스 정의의 일부로 존재하지만 데이터를 제공하려면 객체 인스턴스가 필요합니다.

이론적으로 인스턴스 데이터에 액세스하지 않는 인스턴스 메소드는 정적 컨텍스트에서 작동 할 수 있지만 실제로 인스턴스 메소드가 될 이유는 없습니다. 어쨌든 그것을 금지하는 추가 규칙을 세우는 것이 아니라 언어 디자인 결정입니다.


방금 사람들이 "정적"개념에 너무 일찍 노출되어서는 안된다고 생각했습니다.

정적 메소드는 표준이 아닌 예외입니다. 당신이 OOP를 배우고 싶다면 어쨌든 특히 일찍. (규칙을 예외로 시작하는 이유는 무엇입니까?) 그것은 자바에 대한 반 교육학입니다. 여러분이 배워야 할 "첫 번째"것은 공공 정적 무효입니다. (어쨌든 실제 Java 애플리케이션에는 자체 주요 메소드가 거의 없습니다.)


Java 언어의 규칙에 의해 Java 컴파일러는 "this"와 동등한 것을 삽입한다고 지적 할 가치가 있다고 생각합니다. 명시 적 인스턴스없이 인스턴스 메소드 또는 인스턴스 필드에 액세스하고 있음을 알게되면. 물론 컴파일러는 정적 메서드와 달리 "this"변수가있는 인스턴스 메서드 내에서만이 작업을 수행 할 수 있다는 것을 알고 있습니다.

즉, 인스턴스 메소드에있을 때 다음이 동일하다는 것을 의미합니다.

instanceMethod();
this.instanceMethod();

이것들은 또한 동등합니다 :

... = instanceField;
... = this.instanceField;

컴파일러는 "this"를 효과적으로 삽입하고 있습니다. 특정 인스턴스를 제공하지 않을 때.

컴파일러가 의도 한이 "마법의 도움"비트는 초보자를 혼동 할 수 있습니다. 즉, 인스턴스 호출과 정적 호출은 때때로 같은 구문을 갖는 반면 실제로는 다른 유형과 기본 메커니즘의 호출입니다.

인스턴스 메소드 호출은 다형성을 지원하는 가상 메소드의 동작으로 인해 메소드 호출 또는 디스패치라고도합니다. 디스패치 동작은 사용할 명시 적 객체 인스턴스를 작성했는지 또는 컴파일러가 "this"를 삽입했는지에 관계없이 발생합니다.

정적 메소드 호출 메커니즘은 비 OOP 언어의 함수 호출과 같이 더 단순합니다.

개인적으로 오류 메시지가 잘못되었다고 생각합니다 . " 명시 적 개체 인스턴스를 지정하지 않고 정적 컨텍스트에서 비 정적 메서드를 참조 할 수 없습니다"라고 읽을 수 있습니다 .


컴파일러가 불평하는 것은 단순히 표준 "this"를 삽입 할 수 없다는 것입니다. 이 코드는 정적 메서드 내에 있기 때문에 인스턴스 메서드 내에서와 마찬가지로; 그러나 저자는이 호출을 위해 관심있는 인스턴스를 제공하는 것을 잊었을 수 있습니다.

요컨대 정적 메소드 내에서 인스턴스 메소드를 호출 할 수 있습니다. 호출을위한 명시 적 인스턴스 오브젝트 만 있으면됩니다.


지금까지의 대답은 이유를 설명하지만 여기에 고려해야 할 다른 것이 있습니다.

생성자에 메소드 호출을 추가하여 인스턴스화 가능한 클래스에서 메소드를 호출 할 수 있습니다.

Object instance = new Constuctor().methodCall();

또는

primitive name = new Constuctor().methodCall();

이것은 단일 범위 내에서 인스턴스화 가능한 클래스의 메서드를 한 번만 사용하려는 경우 유용합니다. 단일 범위 내의 인스턴스화 가능한 클래스에서 여러 메서드를 호출하는 경우 참조 가능한 인스턴스를 생성하십시오.


정적 컨텍스트에서 인스턴스 메소드에 액세스하려고하면 컴파일러는 어떤 인스턴스 메소드 (객체에 대한 변수)를 추측 할 수 없습니다. 그러나 항상 객체 참조를 사용하여 액세스 할 수 있습니다.


정적 메소드는 조치를 오브젝트 유형과 연관시키는 반면 비 정적 메소드는 조치를 해당 유형의 오브젝트 인스턴스와 연관시킵니다. 일반적으로 인스턴스와 관련하여 무언가를하는 방법입니다.

전의:

Car 클래스에는 특정 자동차의 세척을 나타내는 wash 메소드가있을 수 있지만 정적 메소드는 type car에 적용됩니다.


메소드가 정적이 아닌 경우, 메소드는 클래스의 인스턴스 레벨 데이터 (정적이 아닌 필드와 같은)에 액세스해야한다는 컴파일러를 "알려줍니다". 클래스의 인스턴스가 작성되지 않으면이 데이터를 사용할 수 없습니다. 따라서 정적 메서드에서 메서드를 호출하려고하면 컴파일러에서 오류가 발생합니다. 실제로 메서드가 클래스의 비 정적 멤버를 참조하지 않으면 메서드를 정적으로 만듭니다.

예를 들어 Resharper에서 클래스의 정적 멤버를 참조하지 않는 비 정적 메소드를 작성하면 "이 메소드는 정적 일 수 있습니다"라는 경고 메시지가 생성됩니다.


컴파일러는 실제로 비 정적 메소드에 인수를 추가합니다. this pointer/reference. This is also the reason why a static method can not use this객체가 없기 때문에을 추가 합니다.


이 뒤에 숨겨진 간단한 이유는 부모 클래스의 정적 데이터 멤버에 액세스 할 수 있지만 (재정의되지 않은 경우에만) 정적이 아닌 데이터 멤버 또는 메서드에 대한 참조가 필요하므로 객체를 통해서만 호출 할 수 있기 때문입니다. .


그래서 당신은 매우 핵심적인 이유를 요구하고 있습니까?

Java로 개발 중이므로 컴파일러는 Java Virtual Machine이 해석 할 수있는 객체 코드를 생성합니다. 어쨌든 JVM은 기계 언어로 실행되는 이진 프로그램입니다 (아마도 운영 체제 및 하드웨어에 특정한 JVM 버전은 프로세서에서 실행할 수있는 기계 코드를 얻기 위해 C와 같은 다른 프로그래밍 언어에 의해 이미 컴파일 된 것입니다). 결국 모든 코드는 기계 코드로 변환됩니다. 따라서 객체 (클래스의 인스턴스)를 만드는 것은 메모리 공간을 예약하는 것과 같습니다 (운영 체제의 CPU 스케줄러가 프로그램을 큐의 맨 위에 놓을 때 프로세서 레지스터가 될 메모리 레지스터). 데이터를 읽고 쓸 수있는 데이터 저장 공간이 있어야합니다. 정적 컨텍스트에서 발생하는 클래스의 인스턴스가없는 경우, 데이터를 읽거나 쓸 메모리 공간이 없습니다. 실제로 다른 사람들이 말했듯이 데이터는 존재하지 않습니다 (처음부터 데이터를 저장하기 위해 메모리 공간을 예약하지 않았기 때문에).

내 영어 죄송합니다! 나는 라틴이야!


비 정적 방법은 객체에 따라 다릅니다. 오브젝트가 작성되면 프로그램에서이를 인식합니다.

객체를 만들기 전에도 정적 메서드를 호출 할 수 있습니다. 정적 메서드는 작업하려는 실제 개체에 의존하지 않는 비교 또는 작업을 수행하는 데 유용합니다.

참고 : https://stackoverflow.com/questions/290884/what-is-the-reason-behind-non-static-method-cannot-be-referenced-from-a-static

반응형