정적이 아닌 변수는 정적 컨텍스트에서 참조 할 수 없습니다
이 테스트 코드를 작성했습니다.
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
연산자 를 사용하여 객체로 인스턴스화 할 때만 작성됩니다 .
클래스의 수명주기는 다음과 같습니다.
- 클래스의 소스 코드가 작성되어 템플릿 또는 패턴 또는 스탬프를 작성하여
new
클래스를 사용 하여 연산자를 사용하여 클래스의 인스턴스를 실제 객체로 만든 다음 객체가 완료되면 객체를 만듭니다.- 가비지 콜렉션 중에 메모리와 같이 보유하고있는 자원을 회수하는 오브젝트를 제거하십시오.
응용 프로그램의 초기 진입 점을 갖기 위해 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();
}
}
나는 당신에게 정적 인 것을 설명하려고 노력할 것입니다. 먼저 모든 정적 변수는 클래스의 특정 인스턴스에 속하지 않습니다. 그들은 클래스의 이름으로 인식됩니다. 정적 메소드는 다시 특정 인스턴스에 속하지 않습니다. 정적 변수에만 액세스 할 수 있습니다. MyClass.myMethod ()를 호출한다고 가정하면 myMethod는 정적 메소드입니다. 메소드 내에서 정적이 아닌 변수를 사용하면 지구상의 지옥은 어떤 변수를 사용할지 어떻게 알 수 있습니까? 그래서 정적 메소드에서만 정적 변수를 사용할 수 있습니다. 나는 특정 인스턴스에 속하지 않는 것을 반복한다.
첫 번째는 클래스의 인스턴스와 클래스 자체의 차이점을 아는 것입니다. 클래스는 특정 속성과 해당 속성의 맥락에서 전체의 동작을 모델링합니다. 인스턴스는 해당 속성에 대한 특정 값을 정의합니다.
정적 키워드에 바인딩 된 것은 클래스 인스턴스의 컨텍스트가 아닌 클래스의 컨텍스트에서 사용할 수 있습니다
위의 결과로
- 메소드 내의 변수는 정적 일 수 없습니다
- 정적 필드 및 메소드는 클래스 이름을 사용하여 호출해야합니다. 예 : MyProgram7.main (...)
정적 필드 / 방법의 수명은 응용 프로그램의 수명과 같습니다.
예를 들어, 자동차는 속성 색상을 가지며 '모션'동작을 나타냅니다. 자동차의 예는 25kmph에서 움직이는 레드 폭스 바겐 비틀입니다.
이제 자동차의 정적 속성은 도로의 바퀴 수 (4)가 될 것이며, 이는 모든 자동차에 적용됩니다.
HTH
인스턴스 메소드 또는 인스턴스 변수를 호출하기 전에 오브젝트 (인스턴스)가 필요합니다. 정적 메서드 컴파일러에서 인스턴스 변수를 호출하면이 변수가 속한 개체를 알 수 없습니다. 정적 메소드에는 객체가 없기 때문에 (한 사본 만 항상). 인스턴스 메소드에서 인스턴스 변수 또는 인스턴스 메소드를 호출하면 this
오브젝트를 참조 합니다. 변수가 생성 된 객체에 속하고 각 객체에 고유 한 인스턴스 메소드 및 변수 사본이 있음을 의미합니다.
정적 변수는로 표시되며 static
인스턴스 변수에는 특정 키워드가 없습니다.
이것은 모든 초보자를위한 정적 키워드에 대해 설명하기에는 약간 다릅니다.
클래스와 객체로 더 많은 작업을 할 때 명확하게 알 수 있습니다.
| * | 정적 : 클래스 이름으로 정적 항목 호출 가능
코드에서 관찰하면 일부 함수는 클래스 이름으로 직접 호출됩니다.
NamCls.NamFnc();
System.out.println();
NamFnc와 println은 키워드 static을 사용하여 선언해야하기 때문입니다.
| * | 비 정적 : 비 정적 항목은 클래스 변수로 호출 가능 정적이 아닌
경우 클래스 변수 가 필요
하고 클래스 변수 뒤에 점을 놓은
다음 함수를 호출하십시오.
NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();
아래 코드는 깔끔하게 설명합니다
| * | 클래스의 정적 및 비 정적 함수 :
public class NamCls
{
public static void main(String[] args)
{
PlsPrnFnc("Tst Txt");
NamCls NamObjVar = new NamCls();
NamObjVar.PrnFnc("Tst Txt");
}
static void PlsPrnFnc(String SrgPsgVal)
{
System.out.println(SrgPsgVal);
}
void PrnFnc(String SrgPsgVal)
{
System.out.println(SrgPsgVal);
}
}
| * | 클래스 내부의 정적 및 비 정적 클래스 :
public class NamCls
{
public static void main(String[] args)
{
NamTicCls NamTicVaj = new NamTicCls();
NamTicVaj.PrnFnc("Tst Txt");
NamCls NamObjVar = new NamCls();
NamNicCls NamNicVar = NamObjVar.new NamNicCls();
NamNicVar.PrnFnc("Tst Txt");
}
static class NamTicCls
{
void PrnFnc(String SrgPsgVal)
{
System.out.println(SrgPsgVal);
}
}
class NamNicCls
{
void PrnFnc(String SrgPsgVal)
{
System.out.println(SrgPsgVal);
}
}
}
클래스 파일을로드하는 것은 ClassLoader의 책임입니다. 클래스를 작성할 때 어떤 일이 발생하는지 봅시다.
예 1 :
class StaticTest {
static int a;
int b;
int c;
}
이제 "StaticTest"클래스에 3 개의 필드가 있음을 알 수 있지만 실제로 b, c 멤버 변수는 없습니다. 그러나 왜 ???. 알았어요. 여기서 b, c는 인스턴스 변수입니다. 인스턴스 변수는 객체를 만들 때 메모리를 가져옵니다. 따라서 b, c는 아직 메모리를 얻지 못했습니다. 그것이 b, c의 존재가없는 이유입니다. 그래서 오직 존재합니다. ClassLoader의 경우 a에 대한 정보가 하나만 있습니다. ClassLoader는 아직 인스턴스화되지 않은 객체이므로 b, c를 인식하지 못합니다.
다른 예를 보자 : 예 2 :
class StaticTest {
public void display() {
System.out.println("Static Test");
}
public static void main(String []cmd) {
display();
}
}
이제이 코드를 컴파일하려고하면 CE 오류가 발생합니다. CE : 정적이 아닌 메소드 display ()는 정적 컨텍스트에서 참조 할 수 없습니다.
이제 ClassLoader의 경우 다음과 같습니다.
class StaticTest {
public static void main(String []cmd) {
display();
}
}
예제 2에서 CE 오류는 정적 컨텍스트에서 비 정적 메소드를 호출하기 때문입니다. 따라서 컴파일시 ClassLoader가 메소드 display ()를 인식 할 수 없으므로 컴파일 시간 오류가 발생합니다.
'IT' 카테고리의 다른 글
iOS 6 앱-iPhone 5 화면 크기를 처리하는 방법은 무엇입니까? (0) | 2020.03.29 |
---|---|
IntelliJ IDEA에서 Eclipse의 Ctrl + O (Show Outline) 단축키는 무엇입니까? (0) | 2020.03.29 |
* args와 ** kwargs는 무엇을 의미합니까? (0) | 2020.03.29 |
WiX 트릭과 팁 (0) | 2020.03.29 |
C #에서 필드를 '읽기 전용'으로 표시하면 어떤 이점이 있습니까? (0) | 2020.03.29 |