Java에서 상수를 구현하는 가장 좋은 방법은 무엇입니까? [닫은]

다음과 같은 예를 보았습니다.

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

상수를 감싸서 Constant final 클래스를 선언하는 Constants 클래스를 가질 수 있다고 가정했습니다. 나는 실제로 Java가 전혀 없다는 것을 알고 있으며 이것이 상수를 만드는 가장 좋은 방법인지 궁금합니다.



답변

그것은 아마도 표준이라도 완벽하게 수용 가능합니다.

(public/private) static final TYPE NAME = VALUE;

여기서 TYPEtype NAME은 공백의 밑줄이있는 모든 대문자의 이름이며 VALUE상수 값입니다.

상수를 자체 클래스 또는 인터페이스에 두지 않는 것이 좋습니다.

참고로 : final로 선언되고 변경 가능한 변수는 계속 변경할 수 있습니다. 그러나 변수가 다른 객체를 가리킬 수는 없습니다.

예를 들면 다음과 같습니다.

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

그것은 합법적이며 ORIGIN(3, 0)의 지점이 될 것입니다.


답변

단일 상수 클래스를 사용하지 않는 것이 좋습니다. 당시에는 좋은 생각처럼 보이지만 개발자가 상수를 문서화하지 않고 클래스가 500 개 이상의 상수를 포괄하도록 성장하면 (상대적으로 서로 관련이없는) (응용 프로그램의 완전히 다른 측면과 관련되어 있음) 일반적으로 상수 파일을 완전히 읽을 수 없게 만듭니다. 대신 :

  • Java 5 이상에 액세스 할 수있는 경우 열거 형을 사용하여 응용 프로그램 영역에 대한 특정 상수를 정의하십시오. 응용 프로그램 영역의 모든 부분은 이러한 상수에 대해 상수 값이 아닌 열거 형을 참조해야합니다. 클래스를 선언하는 방법과 비슷한 열거 형을 선언 할 수 있습니다. 열거 형은 아마도 Java 5+의 가장 유용한 기능 일 것입니다.
  • 특정 클래스 또는 해당 서브 클래스 중 하나에 만 유효한 상수가있는 경우 보호 또는 공용으로 선언하고 계층 구조의 최상위 클래스에 배치하십시오. 이런 식으로 서브 클래스는 이러한 상수 값에 액세스 할 수 있습니다 (다른 클래스가 공용을 통해 액세스 할 경우 상수는 특정 클래스에만 유효하지 않습니다).이 상수를 사용하는 외부 클래스는 상수를 포함하는 클래스)
  • 비헤이비어가 정의 된 인터페이스가 있지만 반환 된 값 또는 인수 값이 특정해야하는 경우 다른 구현자가 액세스 할 수 있도록 해당 인터페이스에서 상수를 정의하는 것이 완벽하게 허용됩니다. 그러나 상수를 유지하기 위해 인터페이스를 작성하지 마십시오. 상수를 유지하기 위해 작성된 클래스만큼 나빠질 수 있습니다.

답변

상수를 유지하기 위해 인터페이스를 사용 하는 것은 나쁜 습관입니다 ( Josh Bloch가 명명 한 상수 인터페이스 패턴 ). Josh가 조언하는 내용은 다음과 같습니다.

상수가 기존 클래스 또는 인터페이스에 강력하게 연결되어 있으면 클래스 또는 인터페이스에 추가해야합니다. 예를 들어 Integer 및 Double과 같은 모든 박스형 숫자 기본 클래스는 MIN_VALUE 및 MAX_VALUE 상수를 내 보냅니다. 상수가 가장 잘 열거 형의 멤버로 볼 경우, 당신은 그들을 내 보내야 열거
형입니다. 그렇지 않으면 상수가 아닌 유틸리티 클래스를 사용하여 상수를 내 보내야합니다.

예:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

명명 규칙 정보 :

일반적으로 이러한 필드의 이름은 대문자로 구성되며 단어는 밑줄로 구분됩니다. 이러한 필드에는 기본 값 또는 변경 불가능한 객체에 대한 참조가 포함되어야합니다.


답변

Effective Java (2 판)에서는 상수에 정적 정수 대신 열거 형을 사용하는 것이 좋습니다.

Java로 열거 형에 대한 좋은 글이 있습니다 :
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

이 기사의 끝에서 제기 된 질문은 다음과 같습니다.

언제 열거 형을 사용해야합니까?

답변 :

고정 상수 세트가 필요할 때마다


답변

인터페이스를 사용하지 마십시오.

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

유혹적이지만 캡슐화를 위반하고 클래스 정의의 구별을 흐리게합니다.


답변

다음과 같은 접근 방식을 사용합니다.

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

예를 들어, 나는 Constants.DB.Connection.URL상수를 얻는 데 사용 합니다. 그것은 나에게 더 “개체 지향적으로”보인다.


답변

별도의 클래스에서 정적 최종 상수를 만들면 문제가 발생할 수 있습니다. Java 컴파일러는 실제로 이것을 최적화하고 상수의 실제 값을 참조하는 모든 클래스에 배치합니다.

나중에 ‘Constants’클래스를 변경하고 해당 클래스를 참조하는 다른 클래스에서 하드 재 컴파일을 수행하지 않으면 사용중인 이전 값과 새 값의 조합으로 마무리됩니다.

이를 상수로 생각하는 대신 구성 매개 변수로 생각하고 관리 할 클래스를 작성하십시오. 값이 최종 값이 아니고 getter 사용도 고려하십시오. 앞으로 이러한 매개 변수 중 일부가 실제로 사용자 나 관리자가 구성 할 수 있어야한다고 결정하면 훨씬 쉽게 수행 할 수 있습니다.