Method 영역 : 클래스 정보 보관, 프로그램을 실행하는데 필요한 공통 데이터 관리
Stack 영역: 실제 프로그램이 실행되는 영역, 메서드 실행시 하나씩 쌓임
Hip 영역: 객체(인스턴스)가 생성되는 영역, new 명령어를 사용하면 이 영역을 사용하게 된다. 클래스(틀)로 생성된 객체(인스턴스)들이 존재하는 공간이라고 생각.
메서드 코드는 메서드 영역에
예를들어 A클래스로 100개의 인스턴스를 생성한다면 힙 메모리에 100개의 인스턴스가 생성되는데 각각의 인스턴스들은 내부에 같은 메서드와 변수들을 가지게 된다. 각각의 인스턴스들의 변수 값들은 다를 수 있지만 메서드는 공통된 코드를 공유한다. 따라서 객체가 생성될 때 인스턴스 변수에는 메모리가 할당 되지만, 메서드에 대한 새로운 메모리할당은 없다. 왜냐하면 메서드는 메서드 영역에서 관리 되기 때문이다.
새로 생성된 인스턴스 내부의 함수가 실행될 때는 메서드가 공유되어진 메서드 영역으로 가 함수를 호출하여 가져와 실행시킨다
스택, 큐 구조
선입선출 - 큐 구조 : 먼저넣은 것이 먼저 나온다 (나는 피시방 알바할 때 관리했던 기억이..)
ex) 선착순 이벤트시 고객이 대기해야 하는 상황이라면 큐 구조를 사용해야한다.
후입선출 - 스택 구조 : 나중에 넣은 것이 먼저 나온다 (제품에 기한이 있는 것들에 관계 되어있을때 사용하면 안될거 같기다하다), 메서드 호출하는 구조에는 스택구조가 맞다고 한다.
package memory;
public class JavaMemoryMain1 {
public static void main(String[] args) {
System.out.println("main start");
method1(10);
System.out.println("main end"); //Ctrl + w
}
static void method1 (int m1){
System.out.println("method1 start");
int cal = m1 * 2;
method2(cal);
System.out.println("method1 end");
}
static void method2 (int m2){
System.out.println("method2 start");
System.out.println("method2 end");
}
}
-------------------------------------------------------------------------
main start
method1 start
method2 start
method2 end < 여기서부터 마지막에 들어간것이 먼저 나옴> ==> 스택구조
method1 end 나갈때는 메서드를 처음 시작했던 지점이 아닌 끝났던 지점으로 다시 돌아온다
main end => 스택 프레임 모두 지워진다
스택 영역과 힙 영역이 같이 사용되는 경우
메서드 실행시 메서드 안의 지역변수는 스택 영역에 포함된다
힙영역 안에서 인스턴스 끼리 서로 참조하고 있어도 외부에서 끌어다 사용할 수 있는 방법이 없기 때문에 GC에 의해 제거된다.
package static1;
public class Data3 {
public String name;
public static int count; // 메서드영역에서 관리한다? => 공용으로 사용할 것
public Data3(String name){
this.name = name;
count++;
}
}
정적변수의 경우 인스턴스 변수에 접근하는 코드는 좋지않다
data4.count 라는 코드는 => 인스턴스를 통해서 접근하는 변수라는 생각이 들 수 있기 때문인데 이런 생각이 들면 다른 개발자가 코드를 가져다 쓸 수도 있기 때문이다. 때문에
Data3.count 라고 사용하는 것이 더 좋다.
Static 메서드
package static2;
public class DecoUtil1 {
public String deco(String str){
return "*" + str + "*";
}
//멤버 변수도 없이 메서드만 띡있는 상태 => 뭔가 정리되었으면 좋겠다?
//인스턴스를 생성하는 이유 => 인스턴스의 변수를 사용하기 위함
//근데 여기에는 인스턴스 변수를 사용하지 않기때문에 뭔가 비효율적인 상태.
//==> static 메서드로 효율적인 코드를 짜보자
}
package static2;
public class DecoUtil2 {
public static String deco(String deco){
return "*" + deco + "*";
}
// 이렇게 정적 메서드를 만들어 인스턴스 생성 없이 클래스명을 통해서 바로 호출이 가능하다
}
package static2;
public class DecoMain2 {
public static void main(String[] args) {
String s = "hello java";
String deco1 = DecoUtil2.deco(s); // 클래스에 가서 바로 메서드를 호출할수있다.
System.out.println("before: "+s);
System.out.println("after: "+deco1);
}
}
클래스 메서드 vs 인스턴스 메서드
클래스 메서드는 클래스를 생성하지 않고 그 클래스 내에 있는 메서드를 직접 호출할 수 있는 static 메서드를 뜻한다.
인스턴스 메서드는 생성자를 통해 인스턴스를 생성해야만 메서드를 호출할수 있다.
Static 메서드는 제약이 있다.
클래스 내부의 기능을 사용시 Static은 정적 메서드나 정적 변수만을 사용할수 있다.
정적 메서드는 인스턴스 변수나 인스턴스 메서드를 사용 할 수 없다.!
But 모든 곳에서 Static을 호출 할 수 있다
Static 메서드는 클래스가 메모리에 로드될 때 함께 생성되며, 인스턴스화 없이 호출할 수 있다. 반면, 인스턴스 변수나 인스턴스 메서드는 클래스의 객체가 생성되어야만 접근할 수 있는 멤버이다. 따라서 Static 메서드는 객체가 생성되기 전에도 호출될 수 있기 때문에, 아직 생성되지 않은 인스턴스 멤버(변수나 메서드)에 접근할 수 없습니다.
정리: 인스턴스는 참조값으로 접근하고, Static은 클래스명으로 접근한다
public static void staticCall ( DecoData data){
data.instanceValue++;
data.instanceMethod();
}
=> 다음과 같이 객체의 참조값을 직접 매개변수로 전달한다면 정적 메서드도 인스턴스의 변수나 메서드를 호출 할 수 있다.
DecoData.staticCall();
DecoData.staticCall();
DecoData.staticCall(); // 이런식으로 클래스.정적메서드 가 자주 쓰일때
Alt + Enter 누르면 임포트 된다
import static static2.DecoData.*; // 모든 메서드 자체를 사용할 것이라는 선언!
'JAVA' 카테고리의 다른 글
[JAVA] OptionalInt 사용법 - 최솟값, 최댓값 뽑을 때 (Feat. stream) (0) | 2025.02.07 |
---|---|
[JAVA] 숫자 형변환 - int형의 나눗셈으로 double형 유리수 만들기 (3) | 2025.02.07 |
[JAVA] 접근제어자 (0) | 2025.02.04 |
[JAVA] 김영한의 실전 자바 기본편 - 절차 지향 프로그래밍 (1) | 2025.01.21 |
[JAVA] 김영한의 실전 자바 - 기본편 : 클래스, 배열 (1) | 2025.01.14 |