[java] Java에서 String 클래스가 final로 선언 된 이유는 무엇입니까?

java.lang.StringJava에서 클래스 가 final로 선언 되었다는 것을 알았을 때 왜 그런지 궁금했습니다. 그때 대답을 찾지 못했지만이 게시물 : Java에서 String 클래스의 복제본을 만드는 방법은 무엇입니까? 내 질문을 상기시켰다.

물론 String은 내가 필요한 모든 기능을 제공하며 String 클래스의 확장이 필요한 작업은 생각하지 못했지만 여전히 누군가가 필요한 것을 알 수는 없습니다!

그렇다면 디자이너가 최종 결정을 내릴 때 디자이너의 의도가 무엇인지 아는 사람이 있습니까?



답변

변경 불가능한 객체 로 문자열을 구현하는 것이 매우 유용 합니다 . 당신은에 대해 읽어야 불변성 그것에 대해 더 이해하기.

불변 개체의 장점 중 하나 는

중복을 단일 인스턴스로 지정하여 중복을 공유 할 수 있습니다.

( 여기에서 ).

문자열이 최종이 아닌 경우 서브 클래스를 작성하고 “문자열로 볼 때”와 유사하지만 실제로는 다른 두 개의 문자열을 가질 수 있습니다.


답변

위의 답변에서 이미 언급 한 두 가지 이유를 간략히 설명 하는 좋은 기사 입니다.

  1. 보안 : 시스템은 변경 될 걱정없이 민감한 읽기 전용 정보를 전달할 수 있습니다.
  2. 성능 : 불변의 데이터는 스레드 안전을 만드는 데 매우 유용합니다.

그리고 이것은 아마도 그 기사에서 가장 자세한 주석 일 것입니다. Java 및 보안 문제의 문자열 풀과 관련이 있습니다. 문자열 풀에 들어갈 내용을 결정하는 방법에 대해 설명합니다. 문자의 순서가 동일하면 두 문자열이 동일하다고 가정하면 누가 먼저 보안 문제에 도달하는지에 대한 경쟁 조건이 있습니다. 그렇지 않은 경우, 문자열 풀에는 중복 문자열이 포함되므로 우선 문자열을 사용하는 이점을 잃게됩니다. 그냥 읽어 보시겠습니까?


문자열을 확장하면 같고 인턴으로 혼란 스러울 수 있습니다. JavaDoc은 다음과 같습니다.

이 문자열을 지정된 객체와 비교합니다. 인수가 널이 아니고이 오브젝트와 동일한 문자 시퀀스를 나타내는 String 오브젝트 인 경우에만 결과가 참입니다.

java.lang.String최종이 아니라고 가정하면 SafeStringa String와 같고 그 반대도 가능합니다. 그것들은 동일한 문자 시퀀스를 나타 내기 때문입니다.

당신이 적용하면 어떻게 될까 internA를 SafeString– 것 SafeStringJVM의 문자열 풀로 이동? ClassLoader모두는 개체를 SafeString다음 JVM의 수명 동안 제자리에 고정 얻을 것이다으로 보류 참조. 캐릭터 시퀀스를 처음으로 인턴 할 수있는 사람에 대한 경쟁 조건이 생길 수 있습니다. 어쩌면 당신 SafeString이 이길 수도 있고 String, 또는 SafeString다른 클래스 로더에 의해로드 될 수도 있습니다 (따라서 다른 클래스).

당신이 수영장에서 레이스에서 우승했다면, 이것은 진정한 싱글 톤 일 것 secretKey.intern().getClass().getClassLoader()입니다.

또는 JVM은 구체적인 String 객체 (하위 클래스는 없음) 만 풀에 추가되도록하여이 구멍을 차단할 수 있습니다.

등호가 같은 구현 된 경우 있음 SafeString! = String다음 SafeString.intern! = String.internSafeString풀에 추가되어야 할 것이다. 그러면 수영장이 <Class, String>대신 수영장이되며 수영장에 <String>들어가기 위해 필요한 것은 새로운 클래스 로더입니다.


답변

String이 불변이거나 최종적인 가장 중요한 이유는 클래스 로딩 메커니즘에 의해 사용되므로 심오하고 근본적인 보안 측면을 가지고 있기 때문입니다.

문자열이 변경 가능하거나 최종적이지 않은 경우 “java.io.Writer”로드 요청이 “mil.vogoon.DiskErasingWriter”로드로 변경되었을 수 있습니다.

참조 : Java에서 String을 변경할 수없는 이유


답변

String Java의 핵심 클래스이며, 많은 것들이 특정 방식으로 작동합니다 (예 : 불변).

클래스를 만들면 final이러한 가정을 어길 수있는 서브 클래스가 방지됩니다.

지금도 리플렉션을 사용하는 경우 문자열을 끊을 수 있습니다 (값 또는 해시 코드 변경). 보안 관리자를 사용하여 리플렉션을 중지 할 수 있습니다. 경우 String아니었다 final, 모든 사람이 그것을 할 수 있습니다.

선언되지 않은 다른 클래스를 final사용하면 다소 깨진 서브 클래스를 정의 할 수 List있지만 (예를 들어 잘못된 위치에 추가 할 수 있음 ) 적어도 JVM은 핵심 작업의 클래스에 의존하지 않습니다.


답변

브루노가 말했듯이 그것은 불변성에 관한 것입니다. Strings뿐만 아니라 Double, Integer, Character 등과 같은 래퍼도 중요합니다. 여기에는 여러 가지 이유가 있습니다.

  • 스레드 안전
  • 보안
  • Java 자체에서 관리되는 힙 (다른 방식으로 가비지 수집되는 일반 힙과는 다름)
  • 메모리 관리

기본적으로 프로그래머는 문자열이 변경되지 않도록 할 수 있습니다. 또한 작동 방식을 알고 있으면 메모리 관리 기능을 향상시킬 수 있습니다. “hello”와 같이 두 개의 동일한 문자열을 하나씩 만들어보십시오. 디버깅하는 경우 동일한 ID를 가지고 있음을 알 수 있습니다. 즉, 동일한 SAME 개체임을 의미합니다. 이것은 Java가 당신을 그렇게 하자는 사실 때문입니다. 문자열이 변경 가능하면 가능하지 않습니다. 그들은 결코 변하지 않을 것이기 때문에 같은 것을 가질 수 있습니다. 따라서 1,000,000 개의 문자열 “hello”를 작성하기로 결정한 경우 실제로 수행하는 작업은 “hello”에 대한 1,000,000 개의 포인터를 작성하는 것입니다. 문자열이나 함수의 래퍼에 대한 모든 기능을 사용하면 다른 개체가 생성됩니다 (개체 ID를 보면 다시 변경됩니다).

Aditionally 자바 마지막이되지 않습니다 반드시 그 객체는 변경할 수 없습니다 의미 (그것은 ++ 예 : C 다릅니다). 즉, 주소가 가리키는 주소는 변경할 수 없지만 속성 및 / 또는 속성은 변경할 수 있습니다. 따라서 어떤 경우에는 불변성과 최종의 차이를 이해하는 것이 실제로 중요 할 수 있습니다.

HTH

참고 문헌 :


답변

구현을 단순화했을 수도 있습니다. 클래스 사용자가 상속 할 수있는 클래스를 디자인하는 경우 디자인을 고려할 완전히 새로운 사용 사례가 있습니다. X 보호 필드를 사용하여이 작업을 수행하면 어떻게됩니까? 최종적으로 공개 인터페이스를 올바르게 작동시키는 데 집중하고 제대로 작동하는지 확인할 수 있습니다.


답변

많은 좋은 점이 이미 언급되었으므로 Java에서 String을 변경할 수없는 이유 중 하나는 String이 해시 코드를 캐시 하도록 허용 하고 Java의 불변 문자열은 해시 코드를 캐시하고 모든 것을 계산하지는 않는 것입니다 우리는 String의 해시 코드 메소드를 호출 하여 Java의 해시 맵에서 사용되는 해시 맵 키처럼 매우 빠릅니다.

간단히 말해서 String은 변경할 수 없기 때문에 아무도 한 번 작성된 내용을 변경할 수 없으므로 여러 호출에서 String의 hashCode가 동일하게 보장됩니다.

당신이 볼 경우 String클래스로 선언했다

/** Cache the hash code for the string */
private int hash; // Default to 0

hashcode()다음과 같은 기능은 –

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

이미 컴퓨터 인 경우 값을 반환하십시오.