on
클래스 변수와 클래스 메소드
클래스 변수와 클래스 메소드
※ 클래스 변수
인스턴스 변수는 인스턴스가 생성되었을 때 생성된 인스턴스 안에 존재하는 변수이다. 이와 달리 클래스 변수는 인스턴스 생성과 상관없이 존재하는 변수이다.
클래스 내에 선언된 변수 앞에 static 선언을 붙이면 이는 인스턴스 변수가 아닌 클래스 변수가 된다. 이 클래스 변수라는 것은 변수가 선언된 클래스의 모든 인스턴스가 공유하는 변수이다. 즉, 클래스 변수는 인스턴스 내에 존재하지 않고 메모리 공간에 딱 하나만 존재하는 변수를 말하고 이 변수가 선언된 클래스의 인스턴스들은 이 변수에 바로 접근할 수 있는 권한이 있는 것이다.
그리고 이 클래스 변수도 접근 수준 지시자의 규칙을 적용받기 때문에 public 으로 선언될 경우 어디에서든지 접근이 가능하다. 접근 방법은 인스턴스의 이름을 통해 접근하기도 하고 클래스의 이름을 통해 접근하기도 한다.
앞서 클래스 변수는 인스턴스 생성과 상관이 없다고 했는데, 그렇다면 메모리 공간에 언제 할당되고 초기화 되는 것일까? 클래스 변수는 인스턴스 생성 이전에 메모리 공간에 존재한다. 즉, 클래스 정보가 가상머신에 의해 읽히는 순간 메모리 공간에 할당되고 초기화 된다는 것이다. 그리고 이 초기화와 할당은 인스턴스의 생성과 무관하게 이루어 진다.
예시를 들어보겠다.
import java.io.*; import java.util.*; public class Main { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { System.out.println(InstCnt.instNum); new InstCnt(); System.out.println(InstCnt.instNum); } } class InstCnt{ static int instNum = 100; InstCnt(){ instNum = 0; } }
100 0
위와 같이 클래스 변수는 인스턴스 생성 이전에 메모리 공간에 존재한다는 것을 알 수 있다.
그렇다면 클래스 변수는 언제 유용하게 활용할 수 있을까? 답은 인스턴스 간에 데이터 공유가 필요한 상황에서 사용된다.
예를 들어 공통으로 사용하는 변하지 않는 상수값을 사용해야 할 때 이런식으로 클래스 변수로 선언해두고 사용하면 편리하다.
static final double PI = 3.1415;
※ 클래스 메소드
클래스 내에 정의된 메소드에 static 선언을 하면 클래스 메소드가 된다. 성격과 접근 방법 모두 클래스 변수와 유사하다.
인스턴스 생성 이전부터 접근이 가능하다.
어느 인스턴스에도 속하지 않는다.
그렇다면 이 클래스 메소드는 언제 사용하면 좋을까? 답은 인스턴스(객체)로 굳이 나눌 필요가 없을 때 사용하면 좋다.
예를 들어 계산기를 구현하는 클래스를 만든다고 했을 때, 굳이 인스턴스를 생성해서 사용할 필요가 없기 때문에 클래스 메소드를 통해 사용하면 불필요한 인스턴스의 생성과정을 생략할 수 있다.
이를 통해서 알수 있는 추가적인 사실은 클래스 메소드는 인스턴스에 속하지 않으므로 인스턴스 변수에 접근이 불가능하고, 호출 또한 불가능 하다는 것이다. 인스턴스가 생성되기전에는 메모리 공간에 존재하지도 않기 때문에 먼저 생성이 된 클래스 메소드에서는 인스턴스 멤버에 접근이 불가능 하기 때문이다.
System.out.println();
이젠 위 코드를 보고 out은 System이란 클래스의 이름을 통해 인스턴스 생성 이전에 접근할 수 있으므로 클래스 변수 이고, println은 out이 참조하는 메소드라는 것을 알 수 있다.
※ 다른 용도의 static 선언
static 초기화 블록은 클래스 변수와 마찬가지로 가상머신이 클래스의 정보를 읽어 들일 때(가상 머신이 클래스를 로딩 할 때) 실행이 된다. 따라서 아래 예시와 같이 static 초기화 블록을 사용하여 클래스 변수를 선언과 동시에 초기화할 수 있다.
import java.io.*; import java.time.LocalDate; public class Main { static String date; static { LocalDate nDate = LocalDate.now(); date = nDate.toString(); } public static void main(String[] args) throws IOException { System.out.println(date); } }
static import 선언을 통해서 모든 클래스 변수와 메소드에 대한 접근을 할 수도 있다. 적절히 그리고 최소한으로 사용한다면 도움이 될 수도 있지만 빈번히 사용할 경우 구분이 어려워지기 때문에 오히려 방해가 될 수도 있다.
import static Java.lang.Math.*;
from http://sweet-smell.tistory.com/144 by ccl(A) rewrite - 2021-12-08 02:28:09