바쁜 분은 이것만
main은 static이라 객체 없이 실행된다 → 인스턴스 메서드·변수는 객체를 만들어서 부른다:new 클래스명().메서드()- 객체의 값(필드)을 안 쓰는 계산용 메서드라면
static을 붙여도 된다 - static 필드는 모든 객체가 하나를 같이 쓴다 — 객체마다 다른 값이면 static을 붙이지 않는다
자바를 처음 배울 때 main 안에서 내가 만든 메서드를 부르자마자 non-static method ... cannot be referenced from a static context 에러를 자주 만납니다. "static이 아닌 메서드를 static 영역에서 참조할 수 없다"는 뜻인데, 왜 그런지와 실제로 고치는 방법 두 가지를 OpenJDK 27에서 직접 컴파일해 보며 정리했습니다.
1. 에러 재현: main에서 메서드와 변수를 바로 쓸 때
public class N1 {
int count = 0;
void hello() {
System.out.println("안녕하세요");
}
public static void main(String[] args) {
hello();
count = 5;
}
}
N1.java:9: error: non-static method hello() cannot be referenced from a static context
hello();
^
N1.java:10: error: non-static variable count cannot be referenced from a static context
count = 5;
^
2 errors
메서드는 non-static method, 필드는 non-static variable로 나올 뿐 원인은 같습니다.
hello()와count에는 static이 없으니 객체(인스턴스)에 속한 것입니다.main은static이라 객체를 하나도 만들지 않은 상태에서 실행됩니다.- 그러니 main 안에서 그냥
count라고 쓰면 "어느 객체의 count?"가 정해지지 않아 컴파일러가 막는 것입니다.
2. 해결 ①: 객체를 만들어서 호출하기 (기본)
public class N2 {
int count = 0;
void hello() {
System.out.println("안녕하세요");
}
public static void main(String[] args) {
N2 app = new N2();
app.hello();
app.count = 5;
System.out.println("count = " + app.count);
}
}
안녕하세요
count = 5
new N2()로 객체를 만들고 app.hello()처럼 "이 객체의"를 붙여 부르면 됩니다. 메서드가 필드를 쓰거나, 나중에 객체를 여러 개 만들 수도 있는 구조라면 이 방법이 맞아요.
3. 해결 ②: 메서드에 static 붙이기 (괜찮은 경우)
public class N3 {
static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println("3 + 4 = " + add(3, 4));
System.out.println("Math.max = " + Math.max(3, 4));
}
}
3 + 4 = 7
Math.max = 4
add는 매개변수로 받은 값만 계산하고 객체의 필드를 전혀 쓰지 않습니다. 이런 메서드는 static으로 만들어도 문제가 없고, 객체 없이 바로 부를 수 있어요. 표준 라이브러리의 Math.max()도 같은 이유로 static입니다.
주의할 점은 에러를 없애려고 필드까지 줄줄이 static으로 바꾸는 것입니다. 컴파일은 되지만 다음 4번처럼 의도와 다르게 동작할 수 있어요.
4. static 필드는 모든 객체가 공유한다 (카운터 실측)
public class Counter {
static int total = 0; // 모든 객체가 같이 쓰는 값
int mine = 0; // 객체마다 따로 있는 값
void click() {
total++;
mine++;
}
public static void main(String[] args) {
Counter a = new Counter();
Counter b = new Counter();
a.click();
a.click();
b.click();
System.out.println("a.mine = " + a.mine + ", b.mine = " + b.mine);
System.out.println("a.total = " + a.total + ", b.total = " + b.total);
System.out.println("Counter.total = " + Counter.total);
}
}
a.mine = 2, b.mine = 1
a.total = 3, b.total = 3
Counter.total = 3
a를 두 번, b를 한 번 눌렀더니 mine은 객체마다 따로 2와 1이 됐고, total은 a로 보든 b로 보든 3으로 같습니다. static 필드는 객체마다 생기는 게 아니라 클래스에 하나만 있기 때문이에요. 그래서 Counter.total처럼 클래스 이름으로 읽는 게 정석입니다.
1번 에러를 없애려고 이름·점수 같은 값을 static으로 바꾸면, 객체가 여러 개일 때 마지막에 넣은 값 하나로 덮입니다. 정말 공유할 값에만 static을 씁니다.
5. static 메서드에서 this를 쓸 때
public class N4 {
String name = "백조";
static void printName() {
System.out.println(this.name);
}
public static void main(String[] args) {
printName();
}
}
N4.java:5: error: non-static variable this cannot be referenced from a static context
System.out.println(this.name);
^
1 error
this는 "지금 이 메서드를 부른 객체"인데, static 메서드는 객체 없이 불리니 가리킬 대상이 없습니다. 고치는 방법은 static을 빼서 인스턴스 메서드로 만들거나, 객체를 매개변수로 받는 것입니다.
public class N5 {
String name = "백조";
void printName() {
System.out.println(this.name);
}
static void printName(N5 obj) {
System.out.println(obj.name);
}
public static void main(String[] args) {
N5 n = new N5();
n.printName();
printName(n);
}
}
백조
백조
6. 같은 에러가 나는 경우: 안쪽 클래스를 main에서 new 할 때
클래스 안에 클래스를 만들고 main에서 객체를 만들 때도 똑같은 this 메시지가 나옵니다.
public class N7 {
class Item {
String name = "연필";
}
public static void main(String[] args) {
Item it = new Item();
System.out.println(it.name);
}
}
N7.java:7: error: non-static variable this cannot be referenced from a static context
Item it = new Item();
^
1 error
static이 없는 안쪽 클래스(inner class)는 바깥 클래스의 객체에 붙어서 만들어지는데, main에는 바깥 객체(this)가 없어서입니다. 안쪽 클래스가 바깥 객체의 필드를 쓰지 않는다면 static class로 선언하면 됩니다.
public class N8 {
static class Item {
String name = "연필";
}
public static void main(String[] args) {
Item it = new Item();
System.out.println(it.name);
}
}
연필
바깥 객체가 꼭 필요한 inner class라면 new N7().new Item()처럼 바깥 객체를 먼저 만들어서 생성합니다.
정리: 언제 static을 붙이나
| 상황 | static? | 예 |
|---|---|---|
| 객체마다 값이 다른 필드 | X | 이름, 점수, 잔액 |
| 모든 객체가 같이 쓰는 값 | O | 전체 생성 개수, 상수(static final) |
| 필드를 쓰는 메서드 | X | click(), printName() |
| 매개변수만으로 계산하는 메서드 | O 가능 | add(a, b), Math.max() |
| 바깥 객체를 안 쓰는 안쪽 클래스 | O 가능 | static class Item |
| 에러 메시지 | 해결 |
|---|---|
| non-static method X() cannot be referenced... | new 클래스().X() 또는 X를 static으로 |
| non-static variable X cannot be referenced... | 객체.X로 접근 (공유 값일 때만 static) |
| non-static variable this cannot be referenced... | static 메서드에서 this 제거, 또는 inner class를 static class로 |
참고: Java Language Specification 8.3.1.1 static Fields, 8.4.3.2 static Methods, 8.1.3 Inner Classes and Enclosing Instances, 15.8.3 this; Oracle The Java Tutorials "Understanding Class Members", "Nested Classes"
