상수란?

·2023년 11월 3일
0

🎯개발지식

목록 보기
6/7

고민

우아한테크코스의 1주차에서는 상수가 고정하는 값으로 생각하여 view의 메시지를 상수로 사용했습니다. 하지만 쓰임에 대해 알아가는 도중 static으로 메모리에 할당되어 모든 클래스에서 접근이 가능하다는 것을 알게되었고 무작위로 사용해서는 안될것 같았습니다. 그래서 과연 상수는 어디에 써야할지에 대한 고민과 정확한 쓰임이 필요하다고 느꼈습니다.

상수는 무엇인가?

상수란 변하지 않고 고정된 값을 담는 변수를 의미합니다. 일상생활에서는 하루가 24시간이고 원주율이 3.14인것처럼 고정된 값입니다.

프로그램에서의 상수는 프로그램이 실행과 동시에 선언하여 실행되는 동안은 재할당 금지 입니다. 프로그램 도중에는 수정할 수 없어 공통코드나, 자주사용하는 문자 또는 숫자는 필드로 선언해줍니다. 만약 여러 메소드에 3을 사용할 경우, 3을 4로 바꿀 때 모든 3을 바꾸기 보다는 상수의 변수값만 바꾸면 모든 값이 변경 됨으로 하드코딩을 방지 할 수 있습니다.

public void final도_값변경이_가능하다() {
        //given
        final Map<String, Boolean> collection = new HashMap<>();

        //when
        collection.put("1", true);
        collection.put("2", true);
        collection.put("3", true);
        collection.put("4", true);

        //then
        assertThat(collection.size()).isEqualTo(4);
    }

상수를 알기전 2가지를 알아보자

1. final

Java에서 final 키워드는 여러 컨텍스트에서 한 번만 지정할 수있는 엔티티를 정의하는 데 사용됩니다. 필드, 함수, 클래스에 사용될 수 있는데, 어떤 곳에 사용되냐에 따라 약간씩 다른 의미를 가집니다. 클래스, 함수, 변수가 변하지 못하도록 의도하고 싶다면 final로 선언하면 됩니다.

1.1 원시 타입

로컬 원시 변수에 final로 선언하면 한번 초기화된 변수는 변경할 수 없는 상수값이 됩니다.

public void test() {
        final int x = 1;
        //x = 5; //final의 값은 변경할 수 없음.
    }

1.2 객체 타입

객체 변수에 final로 선언하면 그 변수에 다른 참조 값을 지정할 수 없습니다. 원시 타입과 동일하게 한번 쓰여진 변수는 재변경 불가합니다. 객체의 속성은 변경 가능합니다.

 public void tes() {
        final Pet pet = new Pet();
//        pet = new Pet(); //다른 객체로 변경할수 없음

        pet.setWeight(3); //객체 필드는 변경할 수 있음

    }

1.3 메서드 인자

메서드 인자에 final 키워드를 붙이면, 메서드 안에서 변수값을 변경할 수 없습니다.

public class Pet {
    int weight;
    public void setWeight(final int weight) {
//        weight = 1; //final 인자는 메서드안에서 변경할 수 없음
    }
}

1.4 final 메서드

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

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

class A{
	
    String name = "hi";

    public final void print() {
        System.out.println(name);
    }
}

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

1.5 final 클래스

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

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

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

2. Static

Static(정적)은 고정된이라는 의미를 가지고 있으며, Static 키워드를 통해 정적 변수와 정적 메소드를 만들 수 있다. 이렇게 만들어진 정적 변수나 정적 메소드는 프로그램이 종료되기 전까지 사용할 수 있습니다

2.1 메모리에 고정적으로 할당된다.

Static이 붙지 않은 메서드나 변수의 경우 객체가 생성될 때마다 호출되어 서로 다른 값을 가지고 있을 수 있습니다. 그렇기 때문에 각 객체들에서 공통적으로 하나의 값이 유지되어야 할 경우 static을 유용하게 사용할 수 있습니다.

2.2 객체 생성 없이 사용할 수 있다.

어떤 객체에 소속되어있다는 뜻은 new 키워드를 이용하여 객체를 생성하여야만 해당 변수나 메서드를 사용할 수 있다는 뜻입니다.

public class C1{
	
	public static void print() {
		System.out.println("객체 생성 없이 사용가능");
	}

}

public class A {

	public static void main(String[] args) {
		C1.print();// new 생성 없이 사용가능합니다
	}
}

static 메서드 내에서는 인스턴스 변수를 사용할 수 없다.

Static 메서드는 프로그램 실행과 동시에 메모리에 올라가기 때문에 인스턴스 변수는 사용할 수 없습니다. 인스턴스 변수는 객체를 생성해야만 사용이 가능하기 때문에 객체를 생성하기 전에 먼저 메모리에 올라가는 static 메서드에서는 사용할 수 없습니다

static 주의점

  1. 메모리 문제
  • static은 프로그램 실행 시점에 메모리에 할당을 하며, 웬만하면 프로그램 종료 시점까지 메모리에서 해제되지 않는다.
  1. 동시성 이슈 문제
  • static은 전역에서 접근이 가능하므로 별도의 동기화 전략을 수립해야 한다.(static 값을 바꾸면 전체 값이 바뀌어버림)
  1. 런타임 다형성 불가
  • static으로만 이루어진 메소드를 사용하는 객체의 경우, 해당 객체를 메모리로 할당하여 사용하는 것이 아니고 객체.메소드로 바로 접근하여 호출한다.

상수(static final)

객체마다 저장되지 않고, 클래스에만 포함.
한 번 초기값이 저장되면 변경할 수 없습니다.

상수의 효과적인 사용

1.해당 상수는 객체 내에서 매번 일반 변수로 정의하기 보다는 한 번 정적 변수로 정의하면 메모리를 아낄 수 있습니다.

private static final String ERROR_MESSAGE = "에러입니다";

2.유틸리티 클래스 정의

유틸리티 클래스는 인스턴스 메소드와 인스턴스 변수를 제공하지 않고, 데이터 처리를 위한 정적 메소드만 존재하는 클래스를 말한다. java에서 Math 클래스를 보면, 상수 외에 인스턴스 변수가 하나도 없고 계산을 위한 정적 메소드만 제공한다.

객체의 상태를 이용할 생각이 없고, 여러 객체들의 필요에 의해 데이터를 처리하는 공통 로직이 필요할 때는 static을 사용하여 설계한다.


정리

1.final

  • 한번 정의 후에 변경 불가능

2.static

  • 여러 인스턴스에서 공통적으로 사용

3.static final 맴버 변수 (static final int x = 1)

  • 값과 함께 선언시 프로그램이 종료될때까지 고정

4.instance final 맴버 변수 (final int x = 1)

  • 값 선언 시 해당 블록이 종료될때까지 고정

참고자료

https://doing7.tistory.com/146

https://djkeh.github.io/articles/Why-should-final-member-variables-be-conventionally-static-in-Java-kor/

https://velog.io/@tjddus0302/Java-%EC%83%81%EC%88%98%EB%8A%94-%EC%99%9C-static-final%EB%A1%9C-%EC%84%A0%EC%96%B8%ED%95%A0%EA%B9%8C

https://advenoh.tistory.com/13

https://steady-coding.tistory.com/603

0개의 댓글