[java] 정적이 아닌 변수는 정적 컨텍스트에서 참조 할 수 없습니다

이 테스트 코드를 작성했습니다.

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

그러나 다음과 같은 오류가 발생합니다.

Main.java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

클래스 변수를 인식하는 메소드를 얻으려면 어떻게해야합니까?



답변

클래스와 해당 클래스의 인스턴스의 차이점을 이해해야합니다. 길거리에서 자동차를 보면 어떤 모델이나 유형을 볼 수 없어도 자동차라는 것을 즉시 알 수 있습니다. 이것은 당신이 보는 것을 클래스 “car” 와 비교하기 때문 입니다. 이 클래스에는 모든 자동차와 비슷한 것이 포함되어 있습니다. 템플릿이나 아이디어로 생각하십시오.

동시에, 당신이 보는 자동차는 당신이 기대하는 모든 속성을 가지고 있기 때문에 “car”클래스의 인스턴스입니다 : 그것을 운전하는 누군가가 있고, 엔진, 바퀴가 있습니다.

따라서 클래스는 “모든 자동차는 색상을가집니다”라고 말하고 인스턴스는 “이 특정 자동차는 빨간색입니다”를 말합니다.

OO 세계에서는 클래스를 정의하고 클래스 내부에서 유형 필드를 정의합니다 Color. 클래스가 인스턴스화되면 (특정 인스턴스를 생성 할 때) 메모리가 색상을 위해 예약되며이 특정 인스턴스에 색상을 부여 할 수 있습니다. 이러한 속성은 고유하기 때문에 비 정적입니다.

정적 필드와 메소드는 모든 인스턴스와 공유됩니다. 이들은 특정 인스턴스가 아닌 클래스에 특정한 값을위한 것입니다. 메서드의 경우 일반적으로 전역 도우미 메서드입니다 (예 🙂 Integer.parseInt(). 필드의 경우 일반적으로 상수입니다 (예 : 자동차 유형, 즉 자주 변경되지 않는 제한된 세트가있는 항목).

문제를 해결하려면 런타임에서 인스턴스의 메모리를 예약 할 수 있도록 클래스의 인스턴스를 인스턴스화 (객체 생성)해야합니다 (그렇지 않으면 다른 인스턴스가 원하지 않는 서로 덮어 쓰기).

귀하의 경우이 코드를 시작 블록으로 사용해보십시오.

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

main()메소드는 포함 된 클래스의 인스턴스를 작성합니다 (이상하게 들리지만 main()인스턴스 대신 클래스로 작성 되었으므로 이를 수행 할 수 있음 run()). 그런 다음 인스턴스 메소드 ( ) 를 호출합니다 .


답변

정적 필드와 메소드는 인스턴스가 아닌 클래스 자체에 연결됩니다. 당신은 클래스가있는 경우 A,는 ‘정상적인’방법 b및 정적 방법을 c, 당신은 인스턴스를 만들 a클래스의를 A,에 대한 호출 A.c()과는 a.b()유효합니다. 메소드 c()는 어떤 인스턴스가 연결되어 있는지 알 수 없으므로 비 정적 필드를 사용할 수 없습니다.

당신을위한 해결책은 필드를 정적으로 만들거나 메소드를 비 정적으로 만드는 것입니다. 당신은 다음과 같이 보일 수 있습니다 :

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}


답변

static키워드는 클래스 내의 메서드 나 변수의 라이프 사이클을 수정합니다. static방법 또는 변수는 클래스가로드 될 때 생성된다. 로 선언되지 않은 메소드 또는 변수 static는 클래스를 예를 들어 new연산자 를 사용하여 객체로 인스턴스화 할 때만 작성됩니다 .

클래스의 수명주기는 다음과 같습니다.

  1. 클래스의 소스 코드가 작성되어 템플릿이나 패턴 또는 스탬프를 작성하여
  2. new클래스를 사용 하여 연산자를 사용하여 클래스의 인스턴스를 실제 객체로 만든 다음 객체가 완료되면 객체를 만듭니다.
  3. 가비지 콜렉션 중에 메모리와 같이 보유하고있는 자원을 회수하는 오브젝트를 제거하십시오.

응용 프로그램의 초기 진입 점을 갖기 위해 Java는 Java 프로그램에 동의하거나 특수한 이름의 메소드가 포함 된 클래스가 있어야한다는 규칙을 채택했습니다. 이 특별한 방법을이라고 main()합니다. 기본 메소드를 포함하는 클래스가 인스턴스화되었는지 여부에 관계없이 메소드가 존재 main()해야 static하므로 클래스가로드되는 즉시 main()메소드를 사용할 수 있도록 수정자를 사용하여 메소드를 선언해야합니다 .

결과적 java helloworld으로 일련의 조치 와 같은 명령 행으로 Java 애플리케이션을 시작할 때 발생합니다. 우선, Java Virtual Machine이 시작되고 초기화됩니다. 다음으로 컴파일 된 Java 코드가 포함 된 helloworld.class 파일이 Java Virtual Machine에로드됩니다. 그런 다음 Java Virtual Machine은 helloworld클래스 에서라는 메소드를 찾습니다 main(String [] args). 이 메소드는 static클래스가 실제로 객체로 인스턴스화되지 않은 경우에도 존재하도록 해야 합니다. Java Virtual Machine은 클래스에서 객체를 만들어 클래스의 인스턴스를 만들지 않습니다. 그냥 클래스를로드하고 main()메소드 에서 실행을 시작합니다 .

따라서 클래스의 인스턴스를 객체로 생성 한 다음 static수정 자로 선언되지 않은 클래스의 메서드 및 변수에 액세스 할 수 있습니다 . Java 프로그램이 main()함수로 시작되면 static로드되는 클래스의 일부로 존재하므로 수정자가있는 변수 또는 메소드를 사용할 수 있습니다 .

그러나 수정자가 main()없는 메소드 외부에있는 클래스의 변수 및 메소드는 클래스 static인스턴스가 main()메소드 내에서 오브젝트로 작성 될 때까지 사용할 수 없습니다 . 객체를 생성 한 후 객체의 변수와 메소드를 사용할 수 있습니다. 클래스 static의 객체를 거치지 않고 수정자가없는 클래스의 변수와 메소드를 사용하려는 시도 는 컴파일시 Java 컴파일러에 의해 포착되어 오류로 플래그됩니다.

import java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}


답변

프로그램을 먼저 분석해 봅시다. 프로그램에서 첫 번째 방법은 main()정적 방법이라는 점을 명심하십시오. 그런 다음 해당 방법에 대한 지역 변수 (compareCount, low, high 등)를 선언하십시오. 이 변수의 범위는 정적 또는 비 정적 메소드에 관계없이 선언 된 메소드입니다. 따라서 해당 메소드 외부에서 해당 변수를 사용할 수 없습니다. 이것이 기본 오류입니다.

다음으로 넘어갑니다. 당신은 정적이 당신을 죽이고 있다고 말했다. (당신을 죽일 수도 있지만 프로그램에 생명을 줄뿐입니다!) 먼저 기본 사항을 이해해야합니다. * 정적 메소드는 정적 메소드 만 호출하고 정적 변수 만 사용하십시오. * 정적 변수 또는 정적 메소드는 해당 클래스의 인스턴스에 종속되지 않습니다. (즉, 정적 변수의 상태를 변경하면 클래스의 모든 객체에 반영됩니다) *이 때문에 클래스 변수 또는 클래스 메소드로 호출합니다. 그리고 “정적”키워드에 대해 더 많은 것이 있습니다. 나는 이제 당신이 아이디어를 얻길 바랍니다. 먼저 변수의 범위를 변경하고 정적로 선언하십시오 (정적 메소드에서 사용할 수 있도록).

그리고 당신을위한 충고는 : 당신은 변수와 정적 기능의 범위에 대한 아이디어를 오해했습니다. 그것에 대해 분명한 아이디어를 얻으십시오.


답변

가장 기본적인 것은 정적 변수이거나 정적 메서드는 클래스 수준입니다. 클래스 레벨 변수 또는 메소드는 인스턴스 레벨 메소드 또는 변수보다 먼저로드되며로드되지 않은 것은 사용할 수 없습니다. 따라서 Java 컴파일러는 런타임에 처리되는 것을 컴파일하지 않으면 해결됩니다. 그래서 정적이 아닌 것을 정적 컨텍스트에서 참조 할 수 없다는 오류가 발생하는 이유입니다. 클래스 레벨 범위, 인스턴스 레벨 범위 및 로컬 범위에 대해 읽으면됩니다.


답변

정적 메소드에서 액세스하려면 다음과 같이 정적 멤버 변수 여야합니다.

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...


답변

이제 메소드에서 인스턴스를 추가 / 사용할 수 있습니다

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}