programing

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

copyandpastes 2023. 1. 22. 22:57
반응형

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

가 그 는 그 수업은 가 from from from from from from from from from from from from from from from from from from from from from.java.lang.String자바에서는 최종판정이라고 하는데, 왜 그런가 궁금했어요.그 당시에는 답을 찾지 못했지만, 이 게시물은 다음과 같습니다.Java에서 String 클래스의 복제본을 만드는 방법궁금증이 떠올랐어요

물론 String은 제가 필요로 했던 모든 기능을 제공합니다.String 클래스의 확장이 필요한 조작은 전혀 생각해 본 적이 없습니다만, 그래도 어떤 조작이 필요한지 알 수 없습니다.

그럼, 디자이너들이 최종 결정을 내렸을 때 그 의도가 무엇이었는지 아는 사람이 있나요?

문자열을 불변의 객체로 구현하면 매우 유용합니다.불변성에 대해 좀 더 이해하려면 불변성에 대해 읽어야 한다.

불변의 물체의 한 가지 장점은 다음과 같습니다.

단일 인스턴스를 가리키면 중복 항목을 공유할 수 있습니다.

(여기서)

String이 최종값이 아닌 경우 서브클래스를 만들고 "Strings"로 표시할 때는 비슷하지만 실제로는 다른2개의 스트링을 가질 수 있습니다.

의 답변에서 이미 언급된 두 가지 이유를 요약한 훌륭한 기사입니다.

  1. 보안: 시스템은 기밀 정보의 일부를 변경할 염려 없이 읽을 수 있습니다.
  2. 퍼포먼스: 불변의 데이터는 스레드 세이프를 실현하는 데 매우 유용합니다.

그리고 이것은 그 기사에서 가장 상세한 코멘트일 것이다.Java 문자열 풀 및 보안 문제와 관련이 있습니다.스트링풀에 들어갈 것을 결정하는 방법에 관한 것입니다.두 문자열의 문자가 같은 경우 두 문자열이 동일하다고 가정할 경우 누가 먼저 도착하는지 및 보안 문제와 함께 경쟁 조건이 있습니다.그렇지 않은 경우 문자열 풀에 다중 문자열이 포함되므로 처음부터 해당 문자열을 사용할 수 있는 이점이 없어집니다.직접 읽어봐, 응?


스트링의 연장은 인턴과 동등한 사람들에게 큰 피해를 줄 것이다.JavaDoc은 다음과 같이 말합니다.

이 문자열을 지정된 개체와 비교합니다.인수가 늘이 아니고 이 개체와 동일한 문자 시퀀스를 나타내는 String 개체일 경우에만 결과가 True가 됩니다.

java.lang.String것이 , 최종적인 것이었다.SafeString와 수 String 같은 글자의 이기 때문에, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.왜냐하면, 같은 문자 시퀀스를 나타내기 때문입니다.

만약 당신이 지원한다면 어떻게 될까요?intern a까지SafeStringSafeStringJVM j j j j j j j j?ClassLoader " " " " " " " "SafeStringJVM의 라이프 타임 동안 해당 레퍼런스가 잠기게 됩니다.은 누가 가장 으로 만들 수 있을 입니다. 의 캐릭터는 당신의 것이 될 것입니다.SafeString수 , ' 수 있을 것이다.String 「」, 「」의 경우도 있습니다.SafeString다른 클래스 로더에 의해 로드됩니다(다른 클래스가 로드됩니다).

, 이 될 것이고 환경(할 수 것입니다.secretKey.intern().getClass().getClassLoader().

또는 JVM은 구체적인 String 오브젝트(서브클래스 없음)만 풀에 추가함으로써 이 홀을 차단할 수 있습니다.

.SafeString!=StringSafeString.intern!=String.intern , , , , 입니다.SafeString를 풀에 추가해야 합니다.이 풀장이 되는 거죠.<Class, String><String>수영장에 들어가려면 새 클래스 로더만 있으면 돼요

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

String이 변경 가능하거나 최종값이 아닌 경우 "java.io" 로딩 요청.writer'가 mil.vogoon으로 변경되었을 수도 있습니다.DiskErasingWriter"

reference : Java에서 문자열이 불변인 이유

String는 Java에서 매우 핵심적인 클래스이며, 많은 것이 특정 방식으로 작동해야 합니다. 를를들, ,,니다다다

만들기final는 이러한 전제조건을 깨는 서브클래스를 방지합니다.

지금도 리플렉션을 사용하면 스트링을 끊을있습니다(값 또는 해시 코드 변경).보안 관리자를 사용하여 반사를 중지할 수 있습니다.한다면String 않았다final누구나 할 수 있다.

되지 않은 final 부서진할 수 .List예를 들어 잘못된 위치에 추가)하지만 적어도 JVM은 핵심 작업에 종속되지 않습니다.

브루노가 말했듯이 불변의 문제입니다.Strings뿐만 아니라 포장지에 대해서도 마찬가지입니다.이중, 정수, 문자 등여기에는 여러 가지 이유가 있습니다.

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

기본적으로는 프로그래머로서 스트링이 변경되지 않는다는 것을 확신할 수 있습니다.또, 동작 방법을 알면, 메모리 관리를 개선할 수 있습니다.동일한 스트링을 2개 연속으로 작성합니다(예: "hello").디버깅을 하면 동일한 ID를 가지고 있다는 것을 알 수 있습니다.즉, 이 ID가 정확히 같은 오브젝트임을 의미합니다.이는 Java가 이를 가능하게 하기 때문입니다.만약 현이 변이 가능했다면 이것은 긍정적이지 않았을 것이다.그들은 나와 같은 것을 가질 수 있다. 왜냐하면 그들은 절대 변하지 않을 것이기 때문이다.따라서 1,000,000개의 문자열 "hello"를 만들기로 결정했을 경우 "hello"에 대한 1,000,000개의 포인터를 만듭니다.또한 문자열에 함수를 할당하거나 이러한 이유로 래퍼를 지정하면 다른 오브젝트가 생성됩니다(오브젝트 ID를 다시 한 번 살펴보세요).

Java에서 추가적으로 final이라고 해서 오브젝트를 변경할 수 없는 것은 아닙니다(예를 들어 C++와 다릅니다).즉, 주소가 가리키는 주소는 변경할 수 없지만 속성이나 속성은 변경할 수 있습니다.따라서 어떤 경우에는 불변성과 최종성의 차이를 이해하는 것이 매우 중요할 수 있습니다.

HTH

참고 자료:

더 나은 구현이 이루어지지 않도록 하기 위해.물론 인터페이스여야 합니다.

[편집] 아, 더 몰상식한 표가 나오네요답은 지극히 진지하다.몇 번이나 String의 실장을 회피하는 프로그램을 짜야 했기 때문에 퍼포먼스와 생산성이 크게 저하되었습니다.

다른 답변에서 제시된 명백한 이유 외에 String 클래스를 최종화하는 것도 가상 메서드의 퍼포먼스 오버헤드와 관련이 있을 수 있습니다.String은 무거운 클래스이므로 최종적으로는 서브 실장 없이 간접 콜의 오버헤드가 발생하지 않는다는 것을 의미합니다.물론 이제는 가상 호출과 같은 기능을 통해 항상 이러한 최적화를 수행할 수 있습니다.

구현을 단순화하기 위한 것일 수 있습니다.클래스 사용자가 상속할 수 있는 클래스를 설계하는 경우 설계에 고려해야 할 완전히 새로운 사용 사례가 있습니다.X protected 필드를 사용하여 이 작업을 수행하거나 저 작업을 수행하면 어떻게 됩니까?최종적으로는 퍼블릭인터페이스가 올바르게 동작하도록 하는 것에 초점을 맞추고, 견고함을 확인할 수 있습니다.

이미 많은 좋은 점들이 제시되어 있기 때문에 저는 다른 이유를 추가하고 싶습니다.Java에서 String이 불변의 이유 중 하나는 String이 해시 코드를 캐시하고 Java에서 불변의 String이 해시 코드를 캐시하고 String의 해시 코드 메서드를 호출할 때마다 계산하지 않기 때문입니다.이것에 의해, 해시 맵에서 사용되는 해시 맵으로서 매우 빠릅니다.ap(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;
}

이미 컴퓨터일 경우 값을 반환합니다.

다른 답변(보안, 불변성, 퍼포먼스)에 기재되어 있는 이유 외에 다음과 같은 점에 주의해 주십시오.String특별한 언어 지원이 있습니다.쓸 수 있다String리터럴에 대한 지원이 있습니다.+교환입니다.프로그래머 서브클래스 허용String는 다음과 같은 해킹을 장려합니다.

class MyComplex extends String { ... }

MyComplex a = new MyComplex("5+3i");
MyComplex b = new MyComplex("7+4i");
MyComplex c = new MyComplex(a + b);   // would work since a and b are strings,
                                      // and a string + a string is a string.

글쎄요, 제가 맞는지 아닌지 확신이 서지 않지만 Java String은 원시 데이터 유형으로 취급할 수 있는 유일한 개체입니다. String name="filename"으로 String 개체를 만들 수도 있습니다.이제 다른 원시 데이터 유형과 마찬가지로 참조 문자열에 의해 복사되지 않은 으로 복사되는 데이터 유형은 동일한 동작을 가질 것으로 예상되므로 String이 최종적인 이유입니다.저도 그렇게 생각했어요.전혀 비논리적이면 무시해 주세요.

문자열의 최종성은 또한 표준으로 문자열들을 방어합니다.C++에서는 문자열의 서브클래스를 만들 수 있기 때문에 모든 프로그래밍 숍은 독자적인 버전의 문자열을 가질 수 있습니다.이는 강력한 기준의 결여로 이어질 것이다.

대부분의 답변은 String 유형의 오브젝트를 갱신할 수 없는 이유인 불변성과 관련되어 있습니다.여기에는 좋은 논의가 많이 있어 Java 커뮤니티는 불변의 원칙을 채택하는 것이 좋을 것이다.(숨을 참지 않고)

하지만 OP의 질문은 왜 최종적인가 하는 것입니다.왜 연장할 수 없는가?여기 있는 몇몇 사람들은 이것을 떠맡았지만, 나는 여기에 진짜 공백이 있다는 OP에 동의할 것이다.다른 언어를 사용하면 개발자는 유형에 대해 새로운 공칭 유형을 만들 수 있습니다.예를 들어 Haskell에서는 실행 시 텍스트와 동일하지만 컴파일 시 바인드 안전성을 제공하는 다음과 같은 새로운 유형을 만들 수 있습니다.

newtype AccountCode = AccountCode Text
newtype FundCode = FundCode Text

그래서 자바 언어를 향상시키기 위해 다음 제안을 제안합니다.

newtype AccountCode of String;
newtype FundCode of String;

AccountCode acctCode = "099876";
FundCode fundCode = "099876";

acctCode.equals(fundCode);  // evaluates to false;
acctCode.toString().equals(fundCode.toString());  // evaluates to true;

acctCode=fundCode;  // compile error
getAccount(fundCode);  // compile error

(또는 자바에서 벗어나기 시작할 수도 있습니다)

'우리'가 칩시다.Employeegreet.greet은 인쇄하는 Hello everyone!그럼 이게 우리가 예상한 행동입니다.greet

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

그럼 이제 ㅇㅇ, ㅇㅇ로 할게요.GrumpyEmployeeEmployee「」를 덮어씁니다.greet을 사용하다

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

다음 now now now now now now now now now now 。sayHello방법.그것은 걸린다.Employeeinstance를 파라미터로 하여 greet 메서드를 호출합니다.그런데 여기서 얻을 수 있는 것은 입니다.이 동작의 변화는Employee grumpyEmployee = new GrumpyEmployee();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

이 상황은, 다음의 경우에 회피할 수 있습니다.Employee이 개설되었다final할 수 의 양은 String가 래음음음 음음음음음 as로 .final

JVM은 무엇이 불변인지 알고 있습니까?답변은 아니오입니다. 상수 풀에는 모든 불변의 필드가 포함되지만 모든 불변의 필드/오브젝트는 상수 풀에만 저장되지는 않습니다.불변성과 그 특징을 실현하는 방법으로만 구현합니다.Marker를 사용하여 CustomString을 최종화하지 않고 구현할 수 있습니다.풀링에 대한 Java 특수 동작을 제공하는 인터페이스. 이 기능은 아직 대기 중입니다!

스트링을 작성하면 오브젝트입니다.그것을 수정하려면 오브젝트입니다.그것은 불가능합니다.새로운 오브젝트가 생성됩니다.

언급URL : https://stackoverflow.com/questions/2068804/why-is-the-string-class-declared-final-in-java

반응형