- static 변수
public calss MyClass {
static int myStaticVariable = 100;
int myVariable = 200;
}
- 위의 예제로 각 변수가 생성되는 공간에 대해 설명해본다.
- 자바 프로그램을 시작하면 JVM이 클래스 파일을 읽어 필요한 클래스와 변수/메서드들을 메모리에 생성한다.
- 이후 코드에서 그 클래스의 형을 가진 오브젝트를 생성하면 각 오브젝트마다 myVariable을 저장할 메모리 공간이 Heap이라는 메모리 공간에 생기게 된다. 모든 오브젝트는 Heap이라고 부르는 메모리 공간에 생긴다.
- 반면 static 변수는 Heap이 아닌 다른 공간에 생긴다. 이 공간의 이름은 MetaSpace이다.
- 위의 그림처럼 static 변수는 클래스에 귀속되지 각각의 오브젝트에는 귀속되지 않는다.
- 평범한 변수는 object마다 1개 생성되므로 n개의 object가 있을 때 n개 생성된다.
- sstatic 변수는 object가 몇 개이던 단 1개만 생성된다.
- EX 1. 실습
public class Main {
public static void main(String[] args) {
System.out.println(MyClass.myStaticVariable);
}
}
- MyClass에 존재하는 myStaticVariable에 접근하려면 ?
- static 변수는 클래스에 귀속되므로 이 변수를 사용하기 위해서는 <클래스이름>.<static변수이름> 으로 접근해야 한다.
- 클래스에 속하므로 object를 생성하지 않아도 myStaticVariable을 사용할 수 있다.
public class Main {
public static void main(String[] args) {
System.out.println(new MyClass().myVariable);
}
}
- 멤버 변수인 myVarialbe은 'new MyClass()'와 같이 새 오브젝트를 생성하고 이 오브젝트를 참조 해야만 해당 변수를 사용할 수 있다.
public class Main {
public static void main(String[] args) {
new MyClass().myMethod();
System.out.println("----------------");
new MyClass().myMethod();
}
}
// 실행 결과
/**
101
201
--------------
102
201
**/
- 위와 같은 실행 결과가 나온 이유 ?
- 자바를 실행시키면 JVM이 static 변수를 먼저 MetaSpace에 만든다.
- 이후 메인 메서드가 실행되면서 새 object들이 heap 공간에 생성된다.
- myVariable은 object 당 하나 생성되므로 각각의 값이 1씩 늘어나지만 myStaticVariable은 클래스 당 1개 존재하므로 '공유' 변수처럼 사용된다.
- static 메서드
public class MyClass {
static int myStaticVariable = 100;
int myVariable = 200;
public void myMethod() {}
public static void myStaticMethod() {}
}
- static 메서드도 마찬가지로 MetaSpace에 만들어진다.
- 한가지 실습을 해보자! 각각의 메소드에서 myStaticVariable과 myVariable을 사용해보는 것이다.
public class MyClass {
static int myStaticVariable = 100;
int myVariable = 200;
public void myMethod() {
myStaticVariable++;
myVariable++;
System.out.println(myStaticVariable);
System.out.println(myVariable);
}
public static void myStaticMethod() {
myStaticVariable = 3;
myVariable = 4; // non-static field 'myVariable' cannot be referenced from static context
}
}
- 위의 코드에서 myVariable = 4에서 신택스 에러가 난다. 이유는 뭘까?
- MyVlass 안에 myVariable은 설계도이다. 이 뜻은 '언젠가 이 클래스를 이용해 오브젝트를 생성하게 되면 myVariable이라는 변수를 만들고 200으로 초기화를 해라' 라는 뜻이다.
- 하지만 myStaticMethod는 자바 프로그램 실행 당시 자바가 클래스 인식을 하면서 static 변수/메서드는 MetaSpace에 먼저 넣어놓게 되어 이때는 myVariable은 메모리 상에 존재하지 않으므로 사용할 수 없다.
- 따라서 myStaticMethod는 비록 같은 클래스 안에 정의되어 있지만 object 생성 시 생성되는 일반적인 멤버 변수/메서드로 볼 수 없다.
- ⁉️ 여기서 궁금증이 생긴거는 그러면 static method는 어느때 사용하면 좋을까 의문이 든다.
- main 메서드
- 이제 왜 main 앞에 static이 붙는지 알겠다.
- 클래스를 로딩하면서 main 메서드가 메모리에 저장되고 자바는 메인 메서드를 보고 제일 먼저 call해야 겠다고 이해 하는 것이다.
더보기
참고 !
클래스는 반드시 object를 생성해 사용한다고 했는데 우리는 main 메서드가 있는 Main 클래스의 object를 만든적이 없다.
다만 public static void main(Stirng[] args)라는 형식을 가진 메서드를 자바가 가장 먼저 실행시킨다는 특징이 있다.
- static class
- static class에 대하여 설명하기 전에 내부 class의 정의 부터 살펴보자!
public class Test {
class InnerClass {
// InnerClass
}
static class InnerStaticClass {
// static InnerClass
}
public static void main(String[] args) {
Test.InnerClass innerClass1 = new Test().new InnerClass();
Test.InnerClass innerClass2 = new Test().new InnerClass();
if (innerClass1 == innerClass2) {
System.out.println("내부 클래스는 같은 참조");
} else {
System.out.println("내부 클래스는 다른 참조");
}
}
}
- 내부 class
- 클래스 안에 클래스가 존재하는 형태이다.
- 보통 내부 클래스의 객체를 만들기 위해서는 상위 클래스의 객체를 먼저 만들어야 한다.
- new 연산자를 두번 사용하여 외부 클래스에 대한 인스턴스를 사용하여 내부 클래스의 인스턴스를 생성한다.
- 위의 코드를 실행 시켜 보면 두 인스턴스는 다른 참조를 갖고 있다.
public class Test {
class InnerClass {
// InnerClass
}
static class InnerStaticClass {
// static InnerClass
}
public static void main(String[] args) {
Test.InnerStaticClass innerClass1 = new Test.InnerStaticClass();
Test.InnerStaticClass innerClass2 = new Test.InnerStaticClass();
if (innerClass1 == innerClass2) {
System.out.println("내부 클래스는 같은 참조");
} else {
System.out.println("내부 클래스는 다른 참조");
}
}
}
- 내부 static class
- 클래스의 객체 2개를 만들어 본 후, 두개의 인스턴스는 같을까?
- 나의 생각은 결과가 같을거라고 생각했다. static 키워드가 붙었으니 변수, 메서드 처럼 이를 공유한다고 생각했다.
- 하지만 결과는 두개 인스턴스의 참조 값이 달랐다.
- 클래스의 역할은 인스턴스를 만드는 설계도의 역할을 할 뿐이지 그 자체가 인스턴스처럼 존재할 수는 없다.
- static 키워드가 클래스에 붙게 되면 인스턴스를 생성하는 방식이 달라지는 것이지 클래스가 갑자기 인스턴스의 역할을 하지는 못한다는 것이다.
- 다만 static이 붙은 class는 상위 클래스의 객체를 만들지 않고 inner class를 사용할 수 있다는 점이 차이이다.
- 클래스의 객체 2개를 만들어 본 후, 두개의 인스턴스는 같을까?
- 내부 클래스를 사용하는 이유
- 외부 클래스와 내부 클래스가 긴밀한 관계를 맺고 있을 때 사용한다.
- 내부 클래스에서 외부 클래스의 멤버에 쉽게 접근 할 수 있다.
- 서로 관련있는 코드를 묶어서 캡슐화를 증가시킬 수 있다.
- 외부에서는 내부 클래스에 접근할 수 없기 때문에 코드의 복잡성도 줄일 수 있다.
- 내부 클래스와 static 내부 클래스의 차이
public class Test {
void myTest() {
}
class InnerClass {
void innerClassMethod() {
Test.this.myTest();
}
}
static class InnerStaticClass {
Test.this.myTest(); // 에러
}
}
- 위의 코드에서 static 내부 클래스에서 Test 클래스의 메소드에 접근하게 되면 컴파일 에러가 발생한다.
- 이유 : Test 객체를 만들기 전에 InnerStaticClass를 사용할 수 있기 때문에 참조할 수 없다는 것이다.
- 이러한 단점에도 static을 사용하지 않는 것의 단점이 더 크기 때문에 내부 클래스는 가능한 static으로 만들어야 한다.
- static이 붙지 않았을 때의 단점
- 참조값을 담아야 하기 때문에 인스턴스 생성시 시간적, 공간적 성능이 낮아진다.
- 외부 인스턴스에 대한 참조가 존재하기 때문에, 가비지 컬렉션이 인스턴스 수거를 하지 못하여 메모리 누수가 생길 수 있다.
- 결론 : static 키워드를 사용하고 싶지 않다면, 내부 클래스가 아닌 별겨의 클래스로 만드는 것이 좋다.
- static이 붙지 않았을 때의 단점
✅ 정리 ✅
- static 변수/메서드는 클래스당 하나 생성된다.
- 프로젝트가 하나의 변수를 공유해야 할 경우 static 변수를 사용한다.
- static 변수/메서드를 사용하기 위해서는 object를 사용할 필요가 없다.
📘 언제 사용할까?
- 프로젝트가 하나의 변수를 공유해야 할 경우 static 변수를 사용한다.
- object의 멤버 변수에 구애 받지 않은 경우, object 생성 없이 메서드를 사용하고 싶은 경우 static 메서들 사용한다.
📌 static Class
- static은 클래스에서도 사용할 수 있지만 이는 중첩 클래스(nested class)를 알아야 하므로 다음에 바로 다루도록 하겠다!
END
- 실무를 하면서 자바의 기초가 얼마나 중요한지 알게 되어 공부를 시작하게 되었다.
- static 키워드를 공부하며 의문점이 생긴 부분이 몇가지 있어 이어서 공부를 해볼까 한다.
- 또한 JVM의 동작방식도 궁금하여 해당 내용도 공부해봐야겠다 싶다!
'배움 기록_실무 ✏️' 카테고리의 다른 글
AWS Simple Queue Service (SQS) (0) | 2023.02.23 |
---|---|
정적 메서드(static method) (0) | 2022.10.17 |
AWS Database Migration Workshop (1) | 2022.05.25 |
구글 OAuth2 인증 방식 (0) | 2022.03.29 |
OAuth 동작 방식 (1) | 2022.03.29 |