객체 인스턴스가 필요한 이유는 멤버 변수(인스턴스)변수를 사용하기 위함
static(정적 변수/클래스 변수)는 공통으로 사용되며, static변수/메서드는 클래스 자체에 접근해 사용
그러나 클래스 static메서드는 static 변수/메서드만 사용할 수 있고, 그 外는 static을 모두 사용
끝으로 main메서드 자체가 정적 메서드이기 static을 사용
1. Static 변수의 이해
[p.15 / Counter] count를 공용으로 사용
public class Counter { //메서드 영역
public int count; //멤버변수 -> 메서드 영역
// 객체로 사용될 경우 -> 힙영역
}
- 클래스의 멤버 변수는 메서드 영역_클래스 정보에 속한다.
- 클래스의 인스턴스마다 별도의 메모리 공간에 할당되어 힙 영역에 저장된다.
[p.15 / Data2]
public class Data2 { //메서드 영역
public String name; //메서드 영역 : 멤버변수
// -> 객체로 사용시 힙 영역
public Data2(String name, Counter counter) { //메서드 자체 -> 메서드 영역
//String name, Counter counter : 매개 변수 -> 스택 영역
this.name = name; //객체 데이터를 받는 것 -> 힙영역
counter.count++; //객체 힙영역 호출 -> 값 증가 -> 힙영역
}
}
[p.8 / DataCountMain2]
public class DataCountMain2 { //메서드 영역
public static void main(String[] args) { //메서드 영역 및 스택 영역
Counter counter = new Counter(); //객체 생성 -> 힙영역
Data2 data1 = new Data2("A", counter); //객체 참조값 접근 -> 힙영역
System.out.println("A = counter " + counter.count); //1 --> 힙영역
Data2 data2 = new Data2("B", counter);
System.out.println("B = counter " + counter.count); //2 --> 원본 counter에 연동
Data2 data3 = new Data2("A", counter);
System.out.println("A = counter " + counter.count); //3
}
}
본격적 static 변수 사용
-> [p.19 / Data3] static(정적 변수/클래스 변수)는 공통으로 사용된다.
public class Data3 { //메서드 영역
public String name; //메서드 영역
//객체로 사용될 시 힙영역
public static int count; //static 변수(정적변수) --> 멤버변수에 추가 : 메서드 영역
public Data3(String name) { //생성자 -> 메서드 영역
//String 자체는 매개변수 --> 스택 영역
this.name = name; //-> 객체의 값 증가
count++; //-> 객체가 생성되면 count값 증가 -> 메서드 영역 (count자체)
}
}
- 인스턴스 변수와는 다르게, 여러곳에서 공유하는 목적으로 사용된다.
[p.19 / Data3 생성자 영역 발췌]
Data3.count++; //-> 객체가 생성되면 count값 증가 -> 메서드 영역 (count자체)
- 단, 자신의 클래스에 있는 정적변수일경우 클래스명을 생략할 수 있다.
[p.20 / DataCountMain3] 클래스 자체에 직접 접근하는 것처럼 이해 (-> 메서드 영역 : static)
public class DataCountMain3 { //메서드 영역
public static void main(String[] args) { //메서드, 스택영역
Data3 data1 = new Data3("A"); //객체 -> 힙영역
System.out.println("A count = " + Data3.count); //카운드 자체 --> 클래스 영역
Data3 data2 = new Data3("A");
System.out.println("B count = " + Data3.count);
Data3 data3 = new Data3("C");
System.out.println("C count = " + Data3.count);
}
}
[p.23 / DataCountMain3_수정] 인스턴스 변수 접근은 추천하지 않는다.
//인스턴스를 통한 접근
Data3 data4 = new Data3("D");
System.out.println("D count = " + data4.count);
//클래스를 통한 접근
System.out.println("D count = " + Data3.count);
*유의할 점 : static 변수는 클래스를 통해 바로 접근할 수도 있고, 인스턴스를 통해서도 접근할 수 있다.
- 코드를 읽을 때, 인스턴스 변수에 접근하는 느낌을 제공하기 때문에 추천하지 않는다.
2. Static 메서드의 이해
[p.24 / DecoUtil1]
public class DecoUtil1 { //메서드 영역
public String deco(String str) { //메서드 영역
//매개변수 -> 스택 영역
return "*" + str + "*"; //중간값 -> 스택 영역
}
}
[p.24 / DecoMain1] 인스턴스 변수가 없어, 단순히 기능을 제공만 함
public class DecoMain1 { //메서드 영역
public static void main(String[] args) { //메서드 영역, 스택 영역
String s = "hello java";
DecoUtil1 utils = new DecoUtil1(); //힙영역
String deco = utils.deco(s); //힙영역 객체 -> 중간변수 deco 저장 : 스택 영역
System.out.println("before = " + s);
System.out.println("before = " + deco);
}
}
본격적 static 메서드 사용
-> [p.25 / DecoUtil2] 정적 메서드는 클래스 명을 통해 바로 호출할 수 있다.
public class DecoUtil2 { //메서드 영역
public static String deco(String str) { //static메서드 추가 -> 메서드 영역
//String 매개변수 -> 스택 영역
return "*" + str + "*"; //중간값 -> 스택 영역
}
}
[p.25 / DecoMain2] 클래스 자체를 바로 호출하는 것 처럼 느껴짐
public class DecoMain2 { //메서드 영역
public static void main(String[] args) { //메서드 영역, 스택 영역
String s = "hello java";
String deco = DecoUtil2.deco(s); //클래스 영역(정적) -> 메서드 영역
//String deco는 중간변수 -> 스택 영역
System.out.println("before = " + s);
System.out.println("after = " + deco);
}
}
[p.26 / DecoData] 클래수 내부에서 static메서드에서는 static만 사용가능 하지만 다른 곳은 static도 사용할 수 있다.
public class DecoData { //메서드 영역
private int instanceValue; //메서드 영역
//객체 사용시 -> 힙영역
private static int staticValue; //정적 변수 -> 메서드 영역 : 공용사용
public static void staticCall() {
//instanceValue++; //힙 영역 증가
//instanceMethod(); //스택 영역
staticValue++; //메서드 영역을 증가시키는 것
staticMethod(); //스택 영역
//즉 static 메서드는 static변수&메서드만 사용이 가능하다.
}
public void instanceCall() {
instanceValue++;
instanceMethod();
staticValue++; //정적 변수 접근 가능
staticMethod();
}
private void instanceMethod() {
System.out.println("instanceValue = " + instanceValue); //힙영역
}
private static void staticMethod() {
System.out.println("staticValue = " + staticValue); //메서드 영역
}
}
- 정적 메서드는 정적 변수, 정적 메서드에 접근할 수 있다.
- 인스턴스 메서드(객체)는 모든 곳에 접근할 수 있다. = 정적 변수, 객체 변수 모두 접근 가능!
[p.28 / DecoDataMain]
public class DecoDataMain { //메서드 영역
public static void main(String[] args) { //메서드 영역, 스택 영역
System.out.println("1. 정적 호출");
DecoData.staticCall(); //정적메서드 사용 -> 메서드 영역
System.out.println("2. 인스턴스 호출1");
DecoData data1 = new DecoData(); //힙 영역
data1.instanceCall(); //힙영역
System.out.println("3. 인스턴스 호출");
DecoData data2 = new DecoData();
data2.instanceCall();
}
}
*정적 메서드가 인스턴스를 사용할 수 없는 이유는 참조값없이 호출하기 때문이다.
[p.29 / DecoData 수정] data 인스턴스 추가
public static void staticCall(DecoData data) {
data.instanceValue++; //힙 영역 증가
data.instanceMethod(); //스택 영역
- 객체 참조값을 제공하면 매서드를 호출할 수 있다.
[p.30 / static import] static import 기능 사용 : import static (폴더명.클래스명.기능)
import static static2.DecoData.staticCall;
public class DecoDataMain { //메서드 영역
public static void main(String[] args) { //메서드 영역, 스택 영역
System.out.println("1. 정적 호출");
staticCall();
staticCall();
staticCall();
staticCall(); //반복 호출
▶ 자바 메모리 구조 이해
https://zoooom-in.tistory.com/57
[김영한_자바기본][7. 자바 메모리 구조와 static] 자바 메모리 구조 이해 / 스택과 큐 자료 구조(p.1-
메서드 영역: 프로그램의 클래스 정보와 정적 변수를 저장하는 공간 힙 영역: 동적으로 생성되는 객체들을 저장하는 공간 스택 영역: 메서드 호출 및 파라미터를 임시로 저장하는 공간 **메인 메
zoooom-in.tistory.com
'Java > [inflearn] 자바 기본' 카테고리의 다른 글
[김영한_자바기본][10. 다형성1] 상속과 메모리 구조(p.1-23) (2) | 2024.02.10 |
---|---|
[김영한_자바기본][9.상속] 상속과 메모리 구조(p.7-20) (0) | 2024.02.08 |
[김영한_자바기본][7. 자바 메모리 구조와 static] 자바 메모리 구조 이해 / 스택과 큐 자료 구조(p.1-12) (0) | 2024.02.07 |
[김영한_자바기본][6. 접근 제어자] 배열 / 접근 제어자 함께 이해하기_문제풀이 쇼핑 카트(p.17) (0) | 2024.02.06 |
[김영한_자바기본][2.기본형과 참조형] 상품 주문 시스템 개발_문제 풀이 해석 보충 (p.30-34) (2) | 2024.02.06 |