열혈 Java 프로그래밍

[윤성우의 열혈 Java 프로그래밍] Chapter 10 클래스 변수, 클래스 메소드

잉여진행중 2020. 8. 3. 20:37

개인적으로 헷갈리는 것 중요한 것 위주로 정리해두고 연습문제를 풀어본 글입니다.

 

- 클래스 변수 

클래스 내 변수 앞에 static 선언 : 인스턴스 변수 -> 클래스 변수

//예제1
class InstCnt {
    static int instNum = 0; //클래스 변수
    
    InstCnt() {  //생성자
        instNum++;
        System.out.println("인스턴스 생성 : " + instNum);
    }
}

class ClassVar {
    public static void main(String[] args) {
        InstCnt cnt1 = new InstCnt();
        InstCnt cnt2 = new InstCnt();
        InstCnt cnt3 = new InstCnt();
    }
}

/*
출력결과

인스턴스 생성 : 1
인스턴스 생성 : 2
인스턴스 생성 : 3

*/

예제1에서

static int instNum을 선언함으로써 변수 instNum은 클래스에 종속되지 않는다.

그렇지만 클래스 내부라 public, private 등 의 영향은 받는다.

같은 클래스에 있는 InstCnt 생성자는 instNum 변수에 자유롭게 접근할 수 있다.

인스턴스를 생성해서 변수의 값을 1씩 증가시킬 때 그 값은 instNum에 공유되어 저장된다.

따라서, 출력 결과가 1이 증가하면서 저장됨이 반복하여 1, 2, 3으로 나타나는 것이다.

 

클래스 변수(static 변수)는 그 클래스의 모든 인스턴스가 공유하는 변수이다.

 

- 클래스 변수 접근 방법

내부 접근 : 변수의 이름으로 직접 접근

외부 접근 : 클래스 또는 인스턴스 이름으로 접근 (public이면 그냥접근가능)

//예제2
class AccessWay {
    static int num = 0; //접근제어 default
    
    AccessWay() {
        incrCnt();
    }
    void incrCnt() {
        num++; //내부 접근
    }
}

class ClassVarAccess {
    public static void main(String[] args) {
        AccessWay way = new AccessWay();
        way.num++; //외부접근1 : 인스턴스 way
        AccessWay.num++; //외부접근2 : 클래스 AccessWay★
        System.out.println("num = " + AccessWay.num);
    }
}

* 인스턴스보다 클래스로 접근하는 것이 둘 다 오류는 발생하지 않지만 더 명확하다.

* 클래스 변수는 생성자 이전에 초기화해야 인스턴스들이 공유할 수 있다. (생성자 내부 시 계속 초기화)

 

static 을 사용하는 상황

: 변수 값의 참조가 목적, 값의 공유가 목적

외부에서 참조해야 하는 경우 public선언

 

- 클래스 메소드

클래스 변수와 유사하다.

인스턴스 생성 전에 접근이 가능하고, 인스턴스에 속하지 않는다.

외부에 기능을 제공할 수 있고, 인스턴수 변수와 관련이 없다.

//예제3
class AAA {
    int num = 0; //인스턴스 변수
    static void addNum(int n) { //클래스 메소드
        num += n;
    }
}
/*클래스 메소드는 인스턴스 변수와 관련이 없으므로 
변수에 직접접근이 불가하다.*/

//예제4
class AAA {
    static int num = 0;
    static void showNum() { //클래스 내 다른 클래스 메소드
        System.out.println(num); //클래스 변수 num에 접근함
    }
    static void addNum(int n) {
        num += n; //클래스 변수는 접근이 가능하다.
        showNum(); //클래스 메소드로 클래스 변수를 호출할 수 있다.
    }
}
/*클래스 메소드는 같은 클래스 내 다른 클래스 메소드와
성격이 같은 클래스 변수에 접근이 가능하다.*/

 

- public static void main(-) {System.out.println(-)}

 

public static void main

main메소드 호출이 클래스 외부에서 이뤄진다.

인스턴스 생성과 관계없이 제일 먼저 호출되는 메소드이다.

System.          out.         println

클래스이름/클래스변수/인스턴스호출

: 클래스에 있는 클래스 변수가 참조하는 인스턴스 메소드를 호출한다!

 

* main메소드는 static이 붙어 클래스와 관련이 없어서 어떤 클래스에 넣던 상관은 없다,

  실행방법만 달라진다. (java ______)

 

- static 초기화 블록

클래스 변수는 생성자 전에 초기화를 해야한다고 했다.

그래서 보편적으로 선언과 동시에 "= 값" 으로 초기화를 한다.

그런데 이때, 초기화 하는 값이 내가 지정하기 힘든 값(얻어와야 하는 값)이면 (ex. 날짜, 시간, 계속해서 바뀌는 값)

static 초기화 블록을 사용한다.

 

import java.time.LocalDate; //import선언은 Ch08

class DateOfExecution { //날짜를 출력하려는 클래스
    static String date;
    
    static { //static 초기화 블록
        LocalDate nDate = LocalDate.now();
        date = nDate.toString();
    }
    
    public static void main(String[] args) {
        System.out.println(date);
    }
}

/*
출력결과

2020-08-03
*/

<문제 10-1.>

class Accumulator {
    static int sum; //클래스변수(값이 공유됨)
    
    static void add(int num) { //클래스메소드
        sum += num; //클래스변수 sum값이 공유되어 저장됨
    }

    static void showResult() { //클래스메소드
        System.out.println("sum = " + sum); //add메소드에서 저장된 sum값이 출력
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) 
            Accumulator.add(i);
        Accumulator.showResult();
    }
}
        
/*
출력결과
sum = 45
*/