method1 End // 이 때 data인스턴스가 힙 영역에서 사라짐(아무도참조하지 않기에)
Main Method End
1)main Method 실행 -> method1 호출
2)Method1 에서 Data 클래스의 인스턴스 생성
3) method2에 인스턴스 참조값 넘기기
4)method2 실행
5) method 2 종료
6) method1 종료--> data인스턴스 삭제
(아무도 참조하지 않는 객체는 삭제)
(GC에 의해)
method1 종료 직후의 모습
스택영역 힙영역
7) mainMethod 종료
3)Static변수
`static`키워드는주로멤버변수와메서드에사용된다.
특정 클래스에서 공용으로사용하기 위해 있는 것!! 예제를 통해 static변수를 사용한 것과
ㅇ사용하지않은것의 차이를 보자
public class Counter {
public int count;
}
public class Data2 {
public String name;
public Data2(String name , Counter counter){
this.name = name;
counter.count++;
}
}
public class DataCountMain2 {
public static void main(String[] args) {
Counter counter = new Counter();
Data2 data1 = new Data2("a",counter);
System.out.println("a count = "+counter.count);
Data2 data2 = new Data2("b",counter);
System.out.println("b count = "+counter.count);
Data2 data3 = new Data2("c",counter);
System.out.println("c count = "+counter.count);
공용 count를 만들기 위해서는 이와같이 만들어야한다
counter클래스를 따로 만든 후
그 인스턴스를 모두가 참조하게 끔 만들어야 함.
메모리낭비가 심함 !
이와같이 힙영역에서 관리해야 할 인스턴스가 많음.
static변수를 사용해 이 점을 해결할 수 있음
(공용변수)
static 변수 사용
publicclassData2{
Stringname;
staticintcount;
Data2(Stringname){
this.name=name;
count++;}}
publicstaticvoidmain(String[]args){
Data2data1=newData2("하");
Data2data2=newData2("하하");
Data2data3=newData2("하하하");
System.out.println(Data2.count);}
static변수는 이런식으로
메서드영역 안에 static영역에서 관리 된다.
정리
`static`변수는쉽게이야기해서클래스인 커피머신이특별히관리하는변수이다.
커피머신은 1개이므로클래스변수도하나만존재한다.
반면에인스턴스변수는커피인스턴스의수만큼존재한다.
(커피머신 하나로 커피를 하나만들면 사라지지 않는다)
용어정리)
멤버변수(필드)의종류**
인스턴스변수:
`static` 이 붙지 않은 멤버 변수, 예) `name`
`static` 이붙지않은멤버변수는인스턴스를생성해야사용할수있고, 인스턴스에소속되어있다
. 따라서인스턴스변수라한다.
인스턴스변수는인스턴스를만들때마다새로만들어진다.
클래스변수:
`static` 이 붙은 멤버 변수, 예) `count`
클래스변수, 정적변수, `static`변수등으로부른다.
**용어를모두사용하니주의하자**
`static` 이붙은멤버변수는인스턴스와무관하게클래스에바로접근해서사용할수있고,
클래스자체에 소속되어있다.
따라서클래스변수라한다.
클래스변수는자바프로그램을시작할때딱 1개가만들어진다.
인스턴스와는다르게보통여러곳에서공유하는목적으로사용된다.
지역변수(매개변수포함)
: 지역변수는스택영역에있는스택프레임안에보관된다.
메서드가종료되면스택프레임도제거
이때해당스택프레임에포함된지역변수도함께제거된다.
따라서지역변수는생존주기가 짧다.
인스턴스변수:
인스턴스에있는멤버변수를인스턴스변수라한다.
인스턴스변수는힙영역을사용한다.
힙영역은 GC(가비지컬렉션)가발생하기전까지는생존하기때문에
보통지역변수보다생존주기가길다.
클래스변수(정적변수):
클래스변수는메서드영역의 static 영역에보관되는변수이다.
메서드영역은프로그램전체에서사용하는공용공간이다.
클래스변수는해당클래스가 JVM에로딩되는순간생성된다.
그리고 JVM이종료될때까지생명주기가이어진다.
따라서가장긴생명주기를가진다.
정적변수 접근법 )
정적변수는 인스턴스를 생성하지않고
클래스를 통해 접근하는 방식을 추천!
(정적변수는 클래스에서 공용으로관리)
static 메서드 )
정적메서드사용법
`static`메서드는`static` 만사용할수있다.
클래스내부의기능을사용할때, 정적메서드는`static` 이붙은
정적메서드나정적변수만사용할수있다.
클래스내부의기능을사용할때, 정적메서드는인스턴스변수나,
인스턴스메서드를사용할수없다.
반대로모든곳에서`static` 을호출할수있다.
정적메서드는공용기능이다.
따라서접근제어자만허락한다면클래스를통해모든곳에서
`static` 을호출할수있다.
멤버메서드의종류
**인스턴스메서드**:
`static` 이붙지않은멤버메서드
**클래스메서드**:
`static` 이붙은멤버메서드
클래스메서드, 정적메서드, `static`메서드등으로부른다.
`static` 이붙지않은멤버메서드는인스턴스를생성해야사용할수있고, 인스턴스에소속되어있다.
따라서인스턴스메서드라한다.
`static` 이붙은멤버메서드는인스턴스와무관하게
클래스에바로접근해서사용할수있고, 클래스자체에소속되어있다.
따라서클래스메서드라한다.
예시를 한번보자
package static2;
public class DecoData {
private int instanceValue;
private static int staticValue;
public static void staticCall(){
//instanceValue++; //인스턴스변수 접근 compile error
//정적메서드가 인스턴스 기능 사용할수 없는 이유
// 참조값이 없는 인스턴스기능을 사용불가 참조값을 직접 전달하면 가능
//instanceMethod(); //인스턴스 메서드 접근 compile error
staticValue++; //정적변수접근
staticMethod(); //정적메서드 접근 //static메서드는 static만 사용가능
}
public void instanceCall(){
instanceValue++; //인스턴스변수 접근
instanceMethod(); //인스턴스 메서드 접근
staticValue++; //정적변수접근
staticMethod(); //정적메서드 접근
}
public static void staticCall(DecoData data){ //오버라이딩
//참조값으로 접근 가능
data.instanceValue++;
data.instanceMethod();
}
private void instanceMethod(){
System.out.println("instanceValue = "+instanceValue);
}
private static void staticMethod(){
System.out.println("staticValue = "+staticValue);
}
}
import static static2.DecoData.* 이란?
static2패키지의 DecoData 클래스를
import하지않고 사용하는 방법 중 하나이다.
(정적 변수, 정적메서드만 사용가능)
package static2;
//import static static2.DecoData.*;
public class DecoDataMain1 {
public static void main(String[] args) {
System.out.println("1.정적 호출");
DecoData.staticCall();
System.out.println("2.인스턴스호출");
DecoData data1 = new DecoData();
data1.instanceCall();
System.out.println("3.인스턴스호출2");
DecoData data2 = new DecoData();
data2.instanceCall(); //새로운 인스턴스 생성으로 인해 (힙영역)instanceValue는 다른 참조값을 가지게 됨 and
// staticValue는 정적변수이므로 (메서드영역)
// 인스턴스생성(참조값이 달라져도)과는 관계가 없음
System.out.println("4.참조값을 인수로받는 정적메서드");
DecoData.staticCall(data1); //정적메서드는 클래스에서 바로불러올수있음 인스턴스를 안 만들어도부를수 있음
//참조값으로 정적메서드 접근 가능
//추가
//인스턴스를 통한 접근
DecoData data3 = new DecoData();
System.out.println("인스턴스로 정적메서드 접근 (추천 안함) 헷갈림");
data3.staticCall(); //인스턴스로접근하는것은 옳지 않은 방법 (클래스로 직접 접근하자 정적메서드 정적변수는 메서드영역임)
}
}