<목차>
• Static이란?
java에서 static은 특정 클래스의 멤버 변수 또는 메서드에 대한 키워드로 해당 키워드를 사용하여 선언된 변수나 메서드는 해당 클래스의 인스턴스와 독립적으로 존재하게 되며, 클래스 정도의 멤버로 간주하게 된다.
즉, 변수 또는 메서드 둘중 하나로 사용되며 클래스 수준의 독립적인 존재가 된다는 것이다.
• Static 변수
Static 변수는 클래스의 모든 인스턴스에서 공유되는 변수로 클래스의 인스턴스를 생성하지 않고도 사용이 가능하다.
예를 들어 '클래스이름.변수이름'의 형태로 접근이 가능하며 static 변수는 프로그램이 시작될 때 초기화 된다.
다시 한 번 강조하지만 해당 클래스의 모든 인스턴스에 의해 공유될 수 있다.
그리고 프로그램이 시작될 때 초기화 된다는 것은 메모리의 이점을 얻을 수 있다는 것이다.(공간 효율)
<<예시1 - 일반적인 변수 선언>>
class Info {
String client = "김갑수"; // 고객 이름
int count = 1; // 방문 횟수 변수
}
public class Static_var {
public static void main(String[] args) {
Info info = new Info();
info.count++; // 인스턴스 생성 시 count 증가
System.out.println(info.client + ", " + info.count);
}
}
예를 들어 '김갑수'라는 고객이 한 명 고정적으로 있다고 가정을 해보자.
client와 count는 매번 메모리를 별도로 할당 받기 때문에 비효율적이다. 여기서 Static 키워드를 사용해 주면 메모리 할당을 한 번만 하고 초기화를 하기 때문에 메모리 관리에 이점이 있다.
<<예시2 - static 변수 선언>>
class Info {
static String client = "김갑수"; // 고객 이름
/* final : static 앞에 사용 시절대 값을 변경 불가 */ static int count = 1; // 방문 횟수 변수
}
public class Static_var {
public static void main(String[] args) {
Info info = new Info();
info.count++; // 인스턴스 생성 시 count 증가
System.out.println(info.client + ", " + info.count);
}
}
김갑수, 2 |
이렇게 static 키워드를 사용해서 선언해주면 메모리 할당을 한 번만 하기 때문에 효율적이다.
다음은 '공유'에 대한 이야기다. 맨 처음 글에서 '클래스 내의 모든 인스턴스에서 공유된다.'라고 말한 적이 있다.
static으로 설정하게 되면 메모리 주소를 사용하기 때문에 해당 메모리에 저장된 static 변수의 값을 공유하게 되는 원리다.
<<공유 예시>>
class num {
int a = 5; // 객체 변수 선언
int b = 13;
num() {
this.a++; // 객체 변수이므로 this를 사용
System.out.println(a + b);
}
}
public class Static_share {
public static void main(String[] args) {
num n1 = new num(); // 서로 다른 메모리를 할당 받는다.
num n2 = new num(); // 메모리 주소가 서로 다르다.
}
}
<결과>
19 19 |
n1과 n2에 할당된 a의 메모리 주소가 다르기 때문에 a의 값은 계속 5 -> 6으로 증가하는 작업을 2번이나 반복한 것이다.
객체변수는 항상 독립적인 값을 갖기 때문에 이런 결과가 발생하는 것이다.
이를 static을 이용하여 수정하면 다음과 같다.
<<공유 예시 - 수정 후>>
class num {
static int a = 5;
static int b = 13;
num() {
a++; // 객체 변수가 아닌 static을 이용한 변수이기 때문에 this 삭제
System.out.println(a + b);
}
}
public class Static_share {
public static void main(String[] args) {
num n1 = new num(); // 서로 (고정된) 동일한 값을 담은 메모리 주소를 받아오므로 같다.
num n2 = new num(); // 메모리 주소가 서로 같다.
}
}
<결과>
a의 값이 연속적으로 증가하는 것을 알 수 있다.
19 20 |
※ static을 사용할 때는 메모리의 효율성보다는 특정 값을 공유하여 사용하기 위한 목적이 더 많다.
• Static 메서드
Static 메서드는 클래스에서 호출할 수 있는 메서드로 'static' 메서드 내에서는 'this' 키워드를 사용하여 현재 객체에 접근할 수 없으며, 오직 클래스의 'static' 멤버들만 접근할 수 있다.
static 메서드는 클래스의 인스턴스와 독립적으로 작동하고, 객체의 상태에 접근할 필요가 없는 유틸리티 메서드나 독립적인 계산 작업을 하는 메서드에 주로 사용된다.
<<예시>>
class run{
public static int sum(int a, int b) { // sum() <- static 메서드가 추가됨.
// 이로 인해 'run.sum()', 객체 생성 없이 클래스를 통해 메서드를 직접 호출 가능해진다.
return a + b;
}
}
class count{
static int final_result = Static_method.result; // result의 값을 받아 온다.
count() {
final_result++; // 값을 하나 증가
// System.out.println(final_result); // 확인용
}
public static int getFinal_result(){ // static 키워드가 메서드 앞에 붙어서 스태틱 메서드가 되었다.
return final_result;
}
}
public class Static_method {
public static int result;
public static void main(String[] args){
result = run.sum(5, 7); // 12
count c1 = new count(); // 13, 12에서 하나 증가
count c2 = new count(); // 14, 13에서 하나 증가
System.out.printf("%d, %d", result, count.getFinal_result()); // 스태틱 메서드를 클래스를 이용하여 호출하였다.
}
}
<결과>
12, 14 |
간단히 말해서 코에 걸면 코걸이 귀에 걸면 귀걸이처럼 변수 앞에 붙으면 정적 변수, 메서드 앞에 정의되면 정적 메서드가 된다고 생각하면 될 것 같다. 단, 위에서 설명했던 공유 개념에 대해서는 명확히 이해해야 할 것 같다.
또 스태틱 메서드 내부에서는 객체변수의 접근이 불가능하다. 단, static 변수라면 스태틱 메서드에서 접근이 가능하다.
<<예시2>>
이번 예시는 전역일 계산기를 만들어 보았다.
날짜를 다루는 예시를 만들어 보고자 해서 만들었지 필자는 이미 군대를 다녀왔다.
import java.time.LocalDate; // 날짜 관련
import java.time.temporal.ChronoUnit; // 두 날짜(시간) 차이를 계산
import java.util.Scanner; // 데이터 입력 관련
class cal_1 { // 전역날을 계산하기 위한 클래스
public static LocalDate get_info() {
LocalDate num = Discharge_Calculator.base;
LocalDate discharge = num.plusMonths(21); // 21개월 군생활 가정
return discharge;
}
}
class cal_2 { // 전역일까지 남은 날짜를 계산하기 위한 클래스
public static long get_count(){ // long은 int보다 더 큰 정수를 저장할 수 있다.
long count_day = ChronoUnit.DAYS.between(LocalDate.now(), cal_1.get_info()); // 두 날짜간 차이 계산
return count_day;
}
}
public class Discharge_Calculator {
public static String enlistment;
public static LocalDate base;
public static void main(String[] args) {
// 입대 날짜 받아오기
Scanner sc = new Scanner(System.in);
System.out.println("입대일을 입력해주세요. ex)20220927");
enlistment = sc.next();
// 입대일 형변환
int year = Integer.parseInt(enlistment.substring(0, 4));
int month = Integer.parseInt(enlistment.substring(4, 6));
int day = Integer.parseInt(enlistment.substring(6, 8));
//sc.close();
base = LocalDate.of(year, month, day); // 날짜 형태로 변환
System.out.println("입대일 : " + base);
// 특정 날짜 받기
System.out.println("전역일 : " + cal_1.get_info()); // 핵심!! 정적 메서드는 클래스를 통해 호출한다.
// 현재 날짜 출력
LocalDate currentDate = LocalDate.now(); // 현재 날짜 가져오기
System.out.println("현재 날짜 : " + currentDate);
// 두 날짜간의 차이 출력
System.out.println("전역까지 남을 일수 : " + cal_2.get_count());
}
}
<결과>
입대일을 입력해주세요. ex)20220927 20231116 <- 타이핑으로 입력한 것 입대일 : 2023-11-16 전역일 : 2025-08-16 현재 날짜 : 2023-07-07 전역까지 남을 일수 : 771 |
'자바(JAVA)' 카테고리의 다른 글
자바 - 변수와 자료의 형태 (1) | 2023.08.08 |
---|---|
자바 - 소스코드(형태, 요소 등) (0) | 2023.08.01 |
자바 - 싱글톤 패턴(Singleton Pattern) (0) | 2023.07.22 |
자바 - 접근 제어자(Access Modifier) (0) | 2023.06.24 |
자바 - 설명과 설치 및 Project 생성 (1) | 2023.06.14 |