Java/[inflearn] 자바 기본

[김영한_자바기본][7. 자바 메모리 구조와 static] static 변수 및 메서드 이해 (p.15-31)

줌인. 2024. 2. 7. 14:29
객체 인스턴스가 필요한 이유는 멤버 변수(인스턴스)변수를 사용하기 위함
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

 

728x90