java 코드를 보다 static 키워드의 실사용성에 대해 궁금한 점이 생겨 찾아보고 정리한 부분을 블로그에 정리하려고 한다.
public class hi {
public static void main(String[] args) {
Solution Foo1(); // static이 붙은 함수'Foo1'의 호출 방식
var sol = new Solution(); // static이 붙지 않은 함수'Foo2'의 호출 방식
sol.Foo2();
}
public class Solution{
public static void Foo1() {} // static 선언
public void Foo2() {}
}
}
new 키워드가 붙은 메모리는 heap공간에 할당이 된다
우리가 올리려는 것에 적당한 heap공간이 있는지 먼저 확인을 해주고 그 만큼의 크기가 있으면 해당 공간에 메모리를 적재한다
그리고 그 메모리에 접근할 수 있는 포인터를 받아서 이렇게 Foo2 함수를 호출할 수 있는 것이다
=> 메모리에 코드가 올라가있지 않으면 Foo2함수를 호출할 수 없다는 말이다.
🤔. Foo1 함수는 어떻게 호출이 될까? ststic 키워드는 어디 메모리에 위치할까?
static은 heap stack과 다르게 static 키워드가 붙은 함수나 변수, 클래스들이 올라갈 수 있는 static 공간이 따로 존재한다
컴파일러는 static이 붙은 함수나 변수, 클래스들을 프로그램 실행과 동시에 static 메모리 공간에 다 적재를 시킨다
=> new를 하지 않지만 컴파일러가 다 적재시켰다는 말이다
=> 이 메모리 공간은 프로그램이 끝나기 전까지 절대 지워지지 않는다
=> 그래서 new 같은 메모리를 생성하지 않아도 바로 접근이 가능하다
알다시피 static 키워드가 붙은 Foo1함수는 이미 시작과 동시에 메모리에 올라가있으니
이 함수 안에서 올라가는 nonStaticVar는 사용자가 new 키워드를 이용해서 메모리에 올리지 않는 한 이런 식으로 에러가 난다 그리고 Foo1이 메모리에 올라가있는 상태에서 nonStaticVar 는 올라와있지 않을 확률이 있다
-> 그래서 static 함수나 static 클래스는 static이 붙은 것들만 참조 가능한 것
public class hi {
public static void main(String[] args) {
int a = 10;
addOne(a);
System.out.println(a);
}
private static void addOne(int a) {
a = a+1;
}
}
-> Q : 이렇게 하면 11이 출력이 될까?
A : 아니다. main에서 사용한 int a와 addOne 변수에서 사용한 int a는 전혀 다른 메모리에 할당된 다른 변수이기 때문에 그대로 10이 출력된다
// 1. 리턴값으로 해결하기
public class hi {
public static void main(String[] args) {
int a = 10;
a = addOne(a); // 변경된 부분 - 밑에서 return한 값 받아주기
System.out.println(a);
}
private static int addOne(int a) { // 변경된 부분 : void -> int로 받기
a = a+1;
return a; // 변경된 부분 - return값으로 돌려주기
}
}
// 2. 클래스 멤버 변수로 해결하기 - 일단 예시이므로 참고만(굳이 이런 식으로 변경x)
public class hi {
int a; // 변경된 부분 : 지역변수가 아닌 이런 식으로 클래스 멤버 변수로 선언하기
public static void main(String[] args) {
Score score = new Score(10); // 변경된 부분 : main에서 클래스 객체를 선언
// public Score(int i) { // 변경된 부분 : 이때 a를 초기화하는 생성자를 하나 만들어놓으면 편하다
// this.a=10;
// }
addOne(score); // 변경된 부분 : a -> score
System.out.println(score.a); // 변경된 부분 : a -> score.a
}
private static int addOne(Score score) { // 변경된 부분 : 파라미터를 클래스 객체로 변경
score.a = score.a+1; // 변경된 부분 : 받은 클래스 객체의 멤버변수인 a값에 1를 더해주는 로직으로 변경
}
}
// 3. static으로 해결하기
public class hi {
static int a;
public static void main(String[] args) {
a = 10;
a = addOne(a);
System.out.println(a);
}
private static int addOne( ) {
a = a+1;
}
}
'Think Deeply' 카테고리의 다른 글
gradle, 왜 쓰는가 (0) | 2024.02.01 |
---|---|
@RequireArgsConstructor와 직접 생성자 만들기의 차이점과 고민 (1) | 2024.01.29 |