프로그래밍 언어/JAVA

static 멤버

· 코딩마이데이

static 멤버의 선언

class StaticSample {
	int n; // non-static 필드
	void g() { ... } // non-static 메소드
    
	static int m; // static 필드
	static void f() { ... } // static 메소드
}

 

static으로 선언된 멤버는 non-static 멤버와 매우 다른 특성을 가집니다.

 

non-static 멤버와 static 멤버의 차이점

static 멤버는 객체를 생성하지 않기도 사용할 수 있는 멤버입니다.

static 멤버는 클래스당 하나만 생성되는 멤버로서 동일한 클래스의 모든 객체들이 공유합니다. 그리고 main() 메소드가 실행되기 전에 이미 생성됩니다.

static 멤버는 static 멤버가 포함된 객체를 생성하기 전에 사용할 수 있습니다.

반면, non-static 멤버는 객체가 생길 때 객체마다 생기며, 다른 객체들과 공유하지 않습니다.

객체가 사라지면 non-static 멤버도 함께 사라지고 더 이상 접근할 수 었습니다. static 멤버는 클래스당 하나씩 생긴다고 해서 클래스 멤버라고도 부르며, non-static 멤버는 각 객체마다 하나씩 생긴다고 해서 인스턴스 멤버라고 부릅니다.

  non-static 멤버 static 멤버
선언 class Sample {
   int n;
   void g() { ... }
}
class Sample {
    static int m;
    static void f() { ... }
}
공간적 특성 멤버는 객체마다 별도 존재
* 인스턴스 멤버라고 부름
멤버는 클래스당 하나 생성
* 멤버는 객체 내부가 아닌 별도의 공간(클    래스 코드가 적재되는 메모리)에 생성
* 클래스 멤버라고 부름
시간적 특성 객체 생성 시에 멤버 생성됨
* 객체가 생길 때 멤버도 생성
* 객체 생성 후 멤버 사용 가능
* 객체가 사라지면 멤버도 사라짐
클래스 로딩 시에 멤버 생성
* 객체가 생기기 전에 이미 생성
* 객체가 생기기 전에도 사용 가능
* 객체가 사라져도 멤버는 사라지지 않음
* 멤버는 프로그램이 종료될 때 사라짐
공유의 특성 공유되지 않음
* 멤버는 객체 내에 각각 공간 유지
동일한 클래스의 모든 객체들에 의해 공유됨

 

static 멤버의 생성과 활용 1: 객체. static 멤버

static 멤버의 생성

StaticSample s1, s2;
s1 = new StaticSample();
s2 = new StaticSample();

 

static 멤버 접근

객체.static필드
객체.static메소드

 

s1.m = 50;
s2.f();

 

static 멤버의 공유

static 멤버를 객체의 멤버로 접근하는 경우

 

static 멤버의 생성 및 활용 2: 클래스명. static 멤버

static 멤버는 클래스당 하나만 있기 때문에 더음과 같이 클래스 이름으로 바로 접근할 수 있습니다.

클래스명.static멤버

 

new에 의해 객체가 생기기 전에 static 멤버를 접근할 수 있습니다.

StaticSample.m = 10;
s1.f(); // 객체 레퍼런스로 static 멤버 f() 호출
StaticSample(); // 클래스명을 이용하여 static 멤버 f() 호출

 

그러나 다음 코드는 틀린 것입니다.

StaticSample.h(); // h()는 non-static이므로 오류
StaticSample.g(); // g()는 non-static이므로 오류

 

static 멤버를 클래스 이름으로 접근

 

static 활용

어떤 변수나 함수도 클래스 바깥에 존재할 수 없으며 클래스의 멤버로 존재하여야 합니다. 이는 자바의 캡슐화 원칙 때문입니다.

한편, 응용 프로그램 작성 시 모든 클래스에서 공유하는 전역 변수(global variable)나 모든 클래스에서 호출할 수 있는 전역 함수(global function)가 필요한 경우가 있습니다.

static 멤버를 가진 대표적인 클래스로 java.lang.Math 클래스가 있습니다.

public class Math {
	public static int abs(int a);
	public static double cos(double a);
	public static int max(int a, int b);
	public static double random();
}

 

응용 프로그램에서 Math의 멤버들을 사용하기 위해 다음과 같이 하지 않습니다.

Math m = new Math(); // 오류. 생성자 Nath()는 private으로 선언되어 있어 객체 생성 안됨
int n = abs(-5);

 

대신 다음과 같이 클래스 이름 Math로 static 클래스의 객체들 사이에서 공유됩니다.

int n = Math.h(-5); // 바른 사용

 

공유 멤버를 만들고자 할 때 활용

static 멤버를 가진 Calc 클래스 작성

class Calc {
    public static int abs(int a) { return a > 0 ? a : -a; }
    public static int max(int a, int b) { return (a > b) ? a : b; }
    public static int min(int a, int b) { return (a > b) ? b : a; }
}

public class CalcEx {
    public static void main(String[] args) {
        System.out.println(Calc.abs(-5));
        System.out.println(Calc.max(10, 8));
        System.out.println(Calc.min(-3, -8));
    }
}

 

static 메소드의 제약 조건

static 메소드는 일반 메소드와 달리 다음 두 가지 제약 사항이 있습니다.

 

static 메소드는 static 멤버만 접근할 수 있습니다.

static 메소드는, 객체 없이도 존재하기 때문에, 객체와 함께 생성되는 non-static 멤버를 사용할 수 없고 static 멤버들만 사용 가능합니다.

반면 non-static 메소드는 static 멤버들을 사용할 수 있습니다.

class StaticMethod {
	int n;
	void f1(int x) { n = x; } // 정상
	void f2(int x) { m = x; } // 정상
    
	static int m;
	static void s1(int x) { n = x; } // 컴파일 오류. static 메소드는 non-static 필드 사용 불가
	static void s2(int x) { f1(3); } // 컴파일 오류. static 메소드는 non-static 메소드 사용 불가
    
	static void s3(int x) { m = x; } // 정상. static 메소드는 static 필드사용 가능
	static void s4(int x) { s3(3); } // 정상. static 메소드는 static 메소드 호출 가능
]

 

static 메소드는 this를 사용할 수 없습니다.

static 메소드는, 객체 없이도 존재하기 때문에, this를 사용할 수 없습니다.

class StaticAndThis {
	int n;
	static int m;
	void f1(int x) { this.n = x; }
	void f2(int x) { this.m = x; } // non-static 메소드에서는 static 멤버 접근 가능
	static void s1(int x) { this.n = x; } // 컴파일 오류. static 메소드는 this 사용 불가
	static voidd s2(int x) { this.m = x; } // 컴파일 오류. static 메소드는 this 사용 불가
}

 

static을 이용한 환율 계산기

import java.util.Scanner;

class CurrencyConverter {
    private static double rate; // 1$에 대한 원화
    public static double toDollar(double won) {
        return won / rate; // 원화를 달러로 변환
    }
    public static double toKWR(double dollar) {
        return dollar * rate; // 달러를 원화로 변환
    }
    public static void setRate(double r) {
        rate = r; // 환율 설정. 원/$1
    }
}

public class StaticMember {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("환율(1달러)>> ");
        double rate = scanner.nextDouble();
        CurrencyConverter.setRate(rate); // 미국 달러 환율 설정
        System.out.println("백만원은 $" + CurrencyConverter.toDollar(1000000) + "입니다.");
        System.out.println("$100는 " + CurrencyConverter.toKWR(100) + "원입니다.");
        scanner.close();
    }
}

 

실행 결과

환율(1달러)>> 1121
백만원은 $892.0606601248885입니다.
$100는 112100.0원입니다.

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

상속  (0) 2025.02.06
final  (0) 2025.02.05
접근 지정자  (0) 2025.02.03
객체의 소멸과 가비지 컬렉션  (0) 2025.02.02
메소드 활용  (1) 2025.02.01