Java에 상수 기능이없는 이유는 무엇입니까?


140

Java에서 상수 뒤에있는 이유를 찾으려고 노력하고 있었는데 Java를 사용하여 final키워드 를 사용하여 상수를 선언 할 수 있다는 것을 알게되었습니다 .

내 질문은 Java가 상수 ( const) 기능을 도입하지 않은 이유 입니다. 많은 사람들이 C ++에서 왔다고 말하고 있으므로 C ++에는 const키워드가 있습니다.

당신의 생각을 공유하십시오.


2
이다const 키워드는 있지만 기본 기능은 없습니다. 제목과 태그를 적절히 수정했습니다.
Lorne의 후작

답변:


142

무거운 C ++ 코딩에서 Java로 갈 때마다 Java의 const-correctness 부족에 적응하는 데 약간의 시간이 걸립니다 . constC ++에서의 사용법은 모르는 경우 상수 변수를 선언하는 것과 크게 다릅니다. 본질적으로 const-pointer라는 특수한 포인터를 통해 액세스 할 때 객체를 변경할 수 없도록합니다 .Java에서는 일반적으로 const-pointer를 반환하려는 위치에서 인터페이스 유형으로 참조를 반환합니다 부작용이 없어야하는 메소드 만 포함합니다. 불행히도, 이것은 언어에 의해 시행되지 않습니다.

Wikipedia는 주제에 대해 다음 정보를 제공합니다.

흥미롭게도 Java 언어 사양은 const를 예약 키워드 (즉, 변수 식별자로 사용할 수없는 키워드)로 간주하지만 의미를 할당하지 않습니다. 키워드의 예약은 Java 언어의 확장이 C ++ 스타일 const 메소드 및 const 유형에 대한 포인터를 포함 할 수 있도록하기 위해 발생한 것으로 생각됩니다. Java에서 프로세스 정확성을 구현하기위한 Java 커뮤니티 프로세스의 개선 요청 티켓은 2005 년에 닫혔으며 이는 const 정확성이 공식 Java 스펙에 절대 영향을 미치지 않을 것임을 암시합니다.


10
final그래도 Java 는 비슷합니다.
reinierpost

62
아닙니다. final예를 들어 메소드는 C ++ const메소드와 완전히 다르게 작동 합니다.
dom0

7
@reinierpost 속성 또는 변수final키워드 는 속성 또는 변수가 한 번만 할당되도록 합니다 . 예를 들어 부작용이있는 메소드를 호출 하여이 객체의 상태를 변경할 수 있습니다. 포인터가 아닌 객체를 참조하는 관점에서 C ++의 할당을 스택하는 것은 다소 유사하지만 그게 전부입니다. 이것은 dom0이 이미 말한 것 외에도 물론입니다. final
Tim

9
final자바에서 C와 같은 작업 ++ 보인다 const값 유형에 대한,하지만 더 C ++ const가 아닌 같은 T&참조 유형에 대한
마크 K 코완

1
final은 정신 분열증 키워드입니다. 재 할당을 방지하는 동시에 변수를 클로저에 노출시키는 데 사용됩니다. 재 할당을 방지하고 싶지만 해당 변수를 노출 시키지는 않지만 할 수있는 방법은 없습니다. 내 의견으로는 언어 기능이 다소 잘못 생각되었습니다.
David Bradley

82

무엇을 const의미
첫째, 실현을하는 "CONST"의 의미 키워드 수단 다른 사람들에게 여러 가지를 :

  • 읽기 전용 참조 -Java final의미론-참조 변수 자체는 다른 인스턴스 (메모리 위치)를 가리 키도록 재 할당 할 수 없지만 인스턴스 자체는 수정할 수 있습니다
  • 읽기 전용 참조 -C const포인터 / 참조 시맨틱-이 참조는 인스턴스를 수정하는 데 사용될 수 없음을 의미합니다 (예 : 인스턴스 변수에 할당 할 수없고 변경 가능한 메소드를 호출 할 수 없음)-참조 변수에만 영향을 미치므로 동일한 인스턴스가 인스턴스를 수정할 수 있습니다
  • 불변 객체 -인스턴스 자체를 수정할 수 없음을 의미-인스턴스에 적용되므로 비 const 참조는 허용되지 않거나 인스턴스를 수정하는 데 사용할 수 없습니다
  • 위의 일부 조합 ?
  • 다른 사람 ?

왜 또는 왜const
두 번째가 아닌지, "pro"대 "con"인수 중 일부를 파고 싶다면이 개선 요청 (RFE) "버그"아래의 설명을 참조하십시오. 이 RFE는 "읽기 전용 참조"유형 "const"기능을 요청합니다. 1999 년에 문을 연 후 2005 년에 Sun에 의해 폐쇄 / 거부 된 "const"주제는 다음과 같이 활발하게 논의되었습니다.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

양쪽에 좋은 주장이 많이 있지만 다음과 같은 자주 언급되는 이유 중 일부는 const다음 과 같습니다.

  • 남용 및 / 또는 오용 될 수 혼란 의미를 가질 수있다 (투시 무엇 const평균 위)
  • 사용 가능한 기능을 복제 할 수 있음 (예 : 불변 인터페이스를 사용하여 불변 클래스 설계)
  • 특징적인 크리프가 발생하여 값으로 객체를 전달하는 것과 같은 다른 의미 변경이 필요할 수 있습니다.

이것이 좋은 이유인지 나쁜 이유인지에 대해 누군가 토론하기 전에, 이것이 나의 이유아니라는 점에 유의하십시오 . 그것들은 내가 RFE 토론을 감추지 않고 얻은 몇 가지 이유의 "장점"입니다. 나는 그들 자신에 반드시 동의하지는 않습니다.-나는 왜 일부 사람들 (내가 아닌)이 const키워드가 좋은 생각이 아닐 수 있다고 느끼는지 인용하려고합니다 . 개인적으로, 나는 더 많은 "const"의미를 모호하지 않은 방식으로 언어에 도입하기를 원합니다.


2
답의 두 번째 부분 만 +1하십시오. 많은 키워드가 사소한 의미를 갖습니다. 가 volatile간단한 이해할 수 있도록? 아니면 final? Meh.
einpoklum

OTOH, Java는 사소한 기능을 최대한 적게 사용하도록 설계되었습니다. 그리고 나는 그들이 그 목표를 달성했다고 말하지 않습니다 (또는 Java가 그 목표에서 멀어지지 않았습니다). 그러나 그러한 이유로 그것을 제외하면 여전히 장점이 있었을 것입니다. 다른 복잡한 것들이 있다는 것은 더 많은 것을 소개하지 않는 더 많은 이유입니다 (또는 D 언어로 끝날 것입니다).
Maarten Bodewes

7

const C ++에서 값이 상수라는 의미는 아닙니다.

const C ++에서 계약의 클라이언트는 그 가치를 변경하지 않을 것을 암시합니다.

const스레드 기반 동시성을 지원하는 환경에 있으면 식 의 값이 변경 되는지 여부 가 더 분명해집니다.

Java는 처음부터 스레드 및 잠금 동시성을 지원하도록 설계되었으므로 의미를 갖도록 용어를 오버로드하여 혼란을 가중시키지 않았습니다 final.

예 :

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

출력 42와 7.

Const가 아닌 별칭이 만들어지면서로 x표시 되었지만 상수는 아닙니다. 모든 컴파일러 가이 동작에 필요한 것은 아닙니다 (모든 컴파일러가 상수를 인라인하도록 허용되어 있음)constxvolatile

더 복잡한 시스템에서는을 사용하지 않고 const / const가 아닌 별명을 const_cast얻게되므로 const가 변경되지 않는 것을 의미하는 습관을들이는 것은 점점 더 위험 해집니다. const단지 코드가 캐스트없이 코드를 변경할 수 없으며 값이 일정하지 않다는 것을 의미합니다.


3
const int x = 42; -x는 상수입니다

2
@Neil const와 non-const 포인터로 별명을 가진 하나의 객체 나 변수가 있다면 const가 아닌 별칭으로 const 별칭의 값을 변경할 수 있습니다. 따라서 const값이 일정하다는 의미는 아닙니다. 이는 값의 클라이언트가 변경하지 않도록 제한되어 있음을 의미합니다. 귀하의 예에는 별칭이 없으므로 모든 사용자가 동일한 제약 조건에 있습니다. 일반적으로 그렇지 않습니다. const그것은 가치가 아닌 고객에게 영향을 미칩니다-그것은 당신이 그것을 바꿀 수 없다는 것이 아니라 바꿀 수 없다고 말합니다.
Pete Kirkham

1
일관성의 정확성 은 프로그래머 수있는 것이 아니라 프로그래머 가해야하는 것에 관한 것 입니다. 나는 당신이 그 점을 가지고 있다고 생각합니다. 인과 독자에게 흥미로울 수있는 몇 센트를 추가하고 싶었습니다. 다음 immutable interface과 같은 디자인 패턴 immutable object은 Java에서 const를 모방하는 또 다른 방법입니다. "True"const는 SealedObject 로 수행 할 수 있습니다 .
Martin Andersson 08

6
프로그램의 결과는 정의되어 있지 않습니다. const_cast는 const 변수를 변경하기 위해 존재하지 않으며 const 변수를 const가 아닌 API로 전달하지만 값을 수정하지도 않습니다. 나는 const가 변경되지 않을 것이라고 생각하는 습관은 좋은 것으로 생각합니다. 왜냐하면 변경하면 프로그램에 사용되는 컴파일러에 따라 언제든지 중단 될 수있는 핵이 포함되어 있기 때문입니다.
Cygon

1
거듭 제곱 된 상수 값을 수정하는 것은 정의되지 않은 동작입니다. 디스크가 이미 포맷되어있을 수 있습니다.
Zhe Yang

5

이것은 약간의 오래된 질문이지만,이 스레드가 오늘 대화에 나왔기 때문에 어쨌든 2 센트를 기부 할 것이라고 생각했습니다.

왜 const가 없는지 정확히 대답하지 못 합니까? 그러나 클래스를 불변으로 만드는 방법 . (안타깝게도 아직 받아 들여진 답변에 대한 의견으로 게시 할만 큼 평판이 충분하지 않습니다)

객체의 불변성을 보장하는 방법은 불변의 클래스를 더 신중하게 디자인하는 것입니다. 이것은 변경 가능한 클래스보다 약간 더주의가 필요합니다.

이것은 Josh Bloch의 유효 Java 항목 15-최소화 최소화로 되돌아갑니다 . 책을 읽지 않았다면 사본을 들고 몇 번 이상 읽습니다. 나는 당신의 비유적인 "자바 게임"을 보장합니다 .

항목 15에서 Bloch는 객체의 상태를 보장하기 위해 클래스의 가변성을 제한해야한다고 제안합니다.

책을 직접 인용하려면 :

불변 클래스는 단순히 인스턴스를 수정할 수없는 클래스입니다. 각 인스턴스에 포함 된 모든 정보는 생성 될 때 제공되며 개체 수명 동안 고정됩니다. Java 플랫폼 라이브러리에는 String, 박스형 기본 클래스 및 BigInteger 및 BigDecimal을 포함하여 많은 불변 클래스가 포함되어 있습니다. 이에 대한 여러 가지 이유가 있습니다. 변경 불가능한 클래스는 변경 가능 클래스보다 설계, 구현 및 사용하기가 더 쉽습니다. 오류가 적고 더 안전합니다.

그런 다음 Bloch는 5 가지 간단한 규칙에 따라 클래스를 변경 불가능하게 만드는 방법을 설명합니다.

  1. 객체의 상태를 수정하는 메소드를 제공하지 마십시오 (예 : setter, aka mutators ).
  2. 클래스를 확장 할 수 없는지 확인하십시오 (이것은 클래스 자체를로 선언 함을 의미합니다 final).
  3. 모든 필드를 확인하십시오 final.
  4. 모든 필드를 확인하십시오 private.
  5. 변경 가능한 구성 요소에 독점적으로 액세스하십시오. (물체를 방어 적으로 복사하여)

자세한 내용은 책의 사본을 선택하는 것이 좋습니다.


3
C ++의 const는 풀 스케일 불변성보다 훨씬 유연합니다. 어떤 의미에서 'const'는 '이 특정 상황 내에서 불변'으로 볼 수 있습니다. 예 : 변경할 수없는 클래스가 있지만 특정 공용 API를 통해 수정되지 않도록하고 싶습니다. Gunslinger47이 제안한대로 인터페이스를 만들고 (공개 API를 위해 그것을 반환하면) Java에서 동일한 것을 달성하지만 소년은 추악합니다 (따라서 대부분의 Java 개발자들은 무시하고 상당한 불필요한 혼란을 초래합니다). .
없음 - 버그 토끼

3

의 C ++ 의미는 constJava와 매우 다릅니다 final. 디자이너가 사용 const했다면 불필요하게 혼란 스러웠을 것입니다.

사실 const예약어는 디자이너가 구현을위한 아이디어를 가지고 제안 const,하지만 그들은 그것에 대하여 결정 이후있다; 이 닫힌 버그를 참조하십시오 . 명시된 이유에는 C ++ 스타일에 대한 지원을 추가 const하면 호환성 문제가 발생할 수 있습니다.


-1

Java에서 "const"변수를 작성하는 방법이 있지만 특정 클래스에 대해서만 가능합니다. 최종 속성을 가진 클래스를 정의하고 서브 클래스로 만드십시오. 그런 다음 "const"를 사용하려는 기본 클래스를 사용하십시오. 마찬가지로 "const"메소드를 사용해야하는 경우 기본 클래스에 추가하십시오. 컴파일러는 기본 클래스의 최종 메소드라고 생각하는 것을 수정할 수 없지만 서브 클래스에서 메소드를 읽고 호출합니다.


예를 들어 주시겠습니까?
NO_NAME

MYString 클래스는 GetString {private final String aaaa; 공개 문자열 getString (); } class MutableString은 GetString을 구현합니다. {private String aaaa2; 공개 문자열 getString (); 공개 문자열 setString ()}
user1122069

-2

상수를 정의하는 두 가지 방법이 있습니다- const그리고 static final정확히 동일한 의미로. 또한 static final행동보다 더 나은 설명const


@ Bozho, 당신은 Const보다 더 나은 행동을 말했다. 당신은 어떤 예를 공유 할 수 있습니다
gmhk

글쎄, 변수는 static(특정 인스턴스에 속하지 않음)이며 final-변경할 수 없습니다.
Bozho

-2

정적 결승을 사용하여 Const와 비슷한 작동하는 것을 만들 수 있습니다. 이는 과거에 이것을 사용했습니다.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;

이것이 효과적이지 않다는 소문을 들었 기 때문에 소문 기반 최적화에 대한 의견이 줄었습니다.
afarley

나는 대답에서 소문을 제거했습니다. 정적 final int를 사용하여 const 스타일 코드를 만들 수 있습니다.
hamish

좋아, 나는 downvote를 제거했다. 어쩌면 다른 downvotes 중 일부는 switch 문에 관한 것일 수 있습니다 (여러 예제와 관련이 있습니까?)
afarley

switch 문에서 cRPM을 const 인 것처럼 사용했습니다. 위의 내용을 고려하면 매우 옳습니다. 예, 스위치를 제거했습니다.
hamish
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.