Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

DOing

[java] static과 final의 차이 (하드 코딩 대신 상수 사용하기) 본문

Java & Kotlin

[java] static과 final의 차이 (하드 코딩 대신 상수 사용하기)

mangdo 2021. 9. 14. 23:49

하드 코딩을 상수로 고치는 과정 중에서 static과 final에 대한 의문이 생겼습니다.

이번 포스팅을 통해 static과 final에 대한 개념을 잡고가려고 합니다.

 


 

 

🖐 잠깐! 하드 코딩이란?

 

프로그램의 소스 코드에 데이터를 직접 입력해서 저장하는 것을 의미합니다.

 

// 테마 내 색깔 개수 확인 
if(3>=colorSet.size() || colorSet.size()>6){ 
    throw new ApiRequestException(" 테마 내 색은 최소 3개, 최대 6개입니다"); 
}

 

하드 코딩을 상수화 하자!

// 테마 내 색깔 개수 확인 
if(COLOR_SIZE_MIN>=colorSet.size() || colorSet.size()>COLOR_SIZE_MAX){ 
    throw new ApiRequestException(" 테마 내 색은 최소 3개, 최대 6개입니다");
}

 

하지만 상수화하던 중 고민이 생기게 되었습니다.

"도대체 뭔차이지..? 하이라이팅이 다르게 되는 걸 보면 분명히 다른건데..... final? static?"

 


 

 

🌱 final

  Java에서 final 키워드는 여러 컨텍스트에서 한 번만 지정할 수있는 엔티티를 정의하는 데 사용됩니다.

필드, 함수, 클래스에 사용될 수 있는데, 어떤 곳에 사용되냐에 따라 약간씩 다른 의미를 가집니다. 공통적으로는 Immutable/Read-only 속성을 선언하는 지시어라고 할 수 있습니다. 만약 클래스, 함수, 변수가 변하지 못하도록 의도하고 싶다면 final로 선언하면 됩니다.

 

 

* final 필드

: 수정할 수 없는 변수가 됩니다. (Immutable)

final로 변수를 선언하게되면 수정될 수 없기 때문에 초기화 값은 필수적입니다. 만약 초기화가 되지 않은 final 필드가 있다면 컴파일 에러가 발생합니다.

final int COLOR_SIZE_MIN = 3;

 

 

 

 

* final 함수

: 메소드 오버라이드를 제한합니다.

자식 클래스에서 재정의하려 할 때 컴파일 오류가 발생합니다. 자신이 만든 메서드를 변경할 수 없게끔 하고싶을때 사용되며 시스템의 코어부분에서 변경을 원치 않는 메서드에 많이 구현되어 있습니다. 

class A{
	
    String name = "홍길동";

    public final void print() {
        System.out.println("제이름은 :"+name+" 입니다.");
    }
}

class B extends A{
	
    String name = "김길동";
	
    // 메서드 오버라이드 불가능
    public void print() {
		
    }
}

 

* final 클래스

: 상속이 불가능한 클래스가 됩니다.

즉, 다른 클래스에서 상속하여 재정의를 할 수 없습니다. 대표적인 클래스로 Integer와 같은 랩퍼(Wrapper) 클래스가 있습니다.

// final 클래스
final class A{
    String name = "홍길동";
}

// 상속 불가능
class B extends A{
	
}

 

 


🌱 Static

  Java에서 Static 키워드는 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 것을 의미합니다. Static이라는 키워드를 사용하여 Static변수와 Static메소드를 만들 수 있는데 다른말로 정적필드와 정적 메소드라고도 하며 이 둘을 합쳐 정적 멤버라고 합니다. 정적 필드와 정적 메소드는 인스턴스에 소속된 멤버가 아니라 클래스에 고정된 멤버이기 때문에 클래스 멤버라고도 합니다. Static 키워드를 통해 정적 멤버를 생성되면 Heap영역이 아닌 Static영역에 할당됩니다. 이를 이해하기위해서는 메모리에 대한 이해가 필요합니다.

출처 : [Java] static변수와 static 메소드 - MangKyu's Diary (tistory.com

 일반적으로 우리가 만든 클래스는 Static 영역에 생성되고, new 연산을 통해 생성한 인스턴스는 Heap영역에 생성됩니다. 이러한 Heap영역의 메모리는 Garbage Collector를 통해 수시로 관리를 받습니다.

 하지만 static 영역에 할당된 정적멤버는 Garbage Collector의 관리 영역 밖에 존재하고있습니다. Static영역에 있는 멤버들은 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만, 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 됩니다. 때문에 Static을 너무 남발하게 되면 시스템 성능에 악영향을 줄 수 있습니다. 

 

 

* 그럼 Static을 언제 사용해야 하지? 

 

1. 모든 인스턴스에 공통된 값을 유지해야하는 멤버 변수

 

 인스턴스를 생성하면, 각 인스턴스들은 서로 독립적기 때문에 서로 다른 값을 유지합니다. 경우에 따라서 각 인스턴스들이 공통적으로 같은 값이 유지되어야 하는 경우 static을 붙입니다.

 

2. 인스턴스 변수를 사용하지 않는 메서드

 

  메서드의 작업내용중에서 인스턴스 변수를 필요로 한다면, static을 붙일 수 없습니다. 반대로 인스턴스변수를 필요로 하지 않는다면, 가능하면 static을 붙이는 것이 좋습니다. 인스턴스를 따로 생성하지 않아도 되며, 메서드 호출시간이 짧아지기 때문에 효율이 높아지기 때문입니다. static을 안붙인 메소드는 실행시 호출되어야 할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸립니다.


- Static 변수 

: 모든 인스턴스에 공통된 값을 유지합니다.

static int color_size_min = 3;

 

- Static 메서드 

: Static 메서드의 대표적 예시로 java.uitl.Math가 있습니다.

이를 이용해서 static 메서드를 작성하면 다음과 같습니다.

static 메서드는 static 변수만 사용할 수 있으며, 인스턴스 변수는 사용할 수 없습니다.

public class staticTest { 
    private String name1 = "홍길동"; 
    private static String name2 = "김길동";
    
    public static void printMax(int x, int y) { 
        System.out.println(Math.max(x, y)); 
    }
    
    public static void printName(){ 
        // System.out.println(name1); 인스턴스 변수라서 불가능
        System.out.println(name2);  // static 변수라서 가능
    } 
}

 

: Static 메서드의 또 다른 대표적 예시로 main()이 있습니다.

main 메소드는 인스턴스 생성과 관계없이 JVM에 의해 호출되므로 static으로 호출되어야 합니다.

public class HighlightBackendApplication {

    public static void main(String[] args) {
        // 메인 함수
    }

}

 


🌱 결론

다시 본래 목적으로 돌아가서 하드코딩을 피하려 상수를 사용하려는 상황일때 어떻게 선언하면 좋을지 생각해보겠습니다.

- 현재 클래스에서만 쓰인다면, prviate로 전체적으로 쓰인다면 public을 사용합니다.

- 한번 정의 후에 변경 불가능해야합니다 -> final

- 여러 인스턴스에서 공통적으로 사용해야합니다. -> static

(Spring은 싱글톤이기때문에 상관없나? 이건 추후에 더 알아보겠습니다. )

 

 

 

 

 

 

 

 

 

참고 사이트:

https://vaert.tistory.com/101

https://blog.lulab.net/programming-java/java-final-when-should-i-use-it/

[Java] static변수와 static 메소드 - MangKyu's Diary (tistory.com)