>Java >java지도 시간 >Java의 문자열 문자열에 대한 자세한 소개

Java의 문자열 문자열에 대한 자세한 소개

黄舟
黄舟원래의
2017-08-11 09:45:031246검색

아래 편집기는 Java 문자열 문자열에 대한 진부한 표현을 제공합니다(반드시 읽어야 할 기사). 편집자님이 꽤 좋다고 생각하셔서 지금 공유하고 모두에게 참고용으로 드리도록 하겠습니다. 편집기를 따라가서 살펴보겠습니다.

Java에는 두 가지 형태의 문자열 객체가 있습니다. 하나는 String str = "hello";와 같은 리터럴 형태이고, 다른 하나는 new와 같은 표준 생성자 객체를 사용하는 것입니다. . String str = new String("hello");

이 상식에 대해서는 자세히 설명하지 않겠습니다.

먼저 String 클래스는 최종 클래스인데 왜 최종 형태로 정의되어 있을까요?

간단히 말하면, 너무 자주 사용되는 데이터 유형의 경우 설계자는 충분히 잘 설계되었으며 상속할 필요가 없다고 생각합니다. 그렇지 않으면 임의 상속 및 재작성이 프로그램 성능을 저하시킬 수 있습니다.

제목에서 알 수 있듯이 심도 있는 내용이므로 JVM 수준에서 String의 작은 동작을 파헤쳐 보겠습니다.

먼저 리터럴 생성 형식을 설명합니다.

문자열 객체를 생성하기 위해 코드에 리터럴 형식이 나타나면 JVM은 먼저 리터럴을 확인하여 문자열에 동일한 내용을 가진 문자가 있는지 확인합니다. 상수 풀 문자열 개체에 대한 참조가 있으면 이 참조가 반환되고, 그렇지 않으면 새 문자열 개체가 생성된 다음 이 참조가 문자열 상수 풀에 저장되고 참조가 반환됩니다.

아래와 같이


String str1 = "hello" ;

처음 만들때는 hello라는 내용의 객체가 없다고 생각했습니다. JVM이 문자열 상수 풀을 통해 hello라는 내용이 포함된 문자열 객체의 존재를 찾을 수 없으면 문자열 객체를 생성한 다음 새로 생성된 객체의 참조를 문자열 상수 풀에 넣고 해당 참조를 변수에 반환합니다. str1

다음에 그러한 코드 조각이 있는 경우


String str2 = "hello" ;

마찬가지로 JVM은 여전히 ​​이 리터럴을 감지해야 합니다. JVM은 문자열 상수 풀을 검색하여 "hello" 내용이 포함된 문자열 개체를 찾습니다. "가 존재하므로 이미 존재할 것입니다. 문자열 개체에 대한 참조는 변수 str2에 반환됩니다. 여기서는 새 문자열 개체가 다시 생성되지 않습니다.

str1과 str2가 동일한 개체를 가리키는지 확인하면 이 코드를 사용할 수 있습니다.


System.out.println(str1 == str2);

결과는 true입니다.

두 번째 유형은 new를 사용하여 생성됩니다.


String str3 = new String("hello");

new를 사용하여 문자열 객체를 생성할 때 문자열 상수 풀에 동일한 내용을 가진 객체에 대한 참조가 있는지 여부에 관계없이 , 새로운 String 객체가 생성됩니다. 그래서 우리는 그것을 테스트하기 위해 다음 코드를 사용합니다.


String str3 = new String("hello");
System.out.println(str1 == str3);

결과는 거짓입니다. 이 두 참조가 서로 다른 개체를 가리킨다는 것을 나타냅니다.

intern

위의 new를 사용하여 생성된 문자열 개체에 대해 이 개체의 참조를 문자열 상수 풀에 추가하려면 intern 메서드를 사용하면 됩니다.

인턴을 호출한 후 먼저 문자열 상수 풀에 개체에 대한 참조가 있는지 확인하고, 존재하는 경우 해당 참조를 변수에 반환합니다.


String str4 = str3.intern();
System.out.println(str4 == str1);

결과는 사실입니다.

질문

전제 조건?

문자열 상수 풀 구현을 위한 전제 조건은 Java의 문자열 객체가 불변이어서 여러 변수가 동일한 객체를 공유하도록 안전하게 보장할 수 있다는 것입니다. Java의 String 개체가 변경 가능하고 참조 작업으로 인해 개체의 값이 변경되면 다른 변수도 영향을 받게 됩니다.

참조 또는 객체

참조 또는 객체가 문자열 상수 풀에 저장되어 있는지 여부에 관계없이 이 문제가 가장 일반적입니다. 문자열 상수 풀은 객체가 아닌 객체 참조를 저장합니다. Java에서는 객체가 힙 메모리에 생성됩니다. 문자열 상수 풀은 힙 메모리의 영구 생성에 존재합니다

장점과 단점

문자열 상수 풀의 장점은 동일한 내용의 문자열 생성을 줄여 메모리 공간을 절약할 수 있다는 것입니다.

단점을 굳이 얘기하자면, 공간 대신 ​​CPU 컴퓨팅 시간이 희생된다는 점입니다. CPU 계산 시간은 주로 문자열 상수 풀에 동일한 내용을 가진 객체에 대한 참조가 있는지 확인하는 데 사용됩니다. 그러나 내부 구현은 HashTable이므로 계산 비용이 저렴합니다.

GC 재활용?

문자열 상수 풀이 공유 문자열 개체에 대한 참조를 보유하고 있기 때문에 이러한 개체를 재활용할 수 없다는 의미입니까?

우선, 질문에 공유된 개체는 일반적으로 작습니다. 내가 아는 한, 이 문제는 이전 버전에도 존재했지만 약한 참조가 도입되면서 이제 이 문제는 사라졌습니다.

인턴용?

关于使用intern的前提就是你清楚自己确实需要使用。比如,我们这里有一份上百万的记录,其中记录的某个值多次为美国加利福尼亚州,我们不想创建上百万条这样的字符串对象,我们可以使用intern只在内存中保留一份即可。

总有例外?

你知道下面的代码,会创建几个字符串对象,在字符串常量池中保存几个引用么?


String test = "a" + "b" + "c";

答案是只创建了一个对象,在常量池中也只保存一个引用。我们使用javap反编译看一下即可得知。

实际上在编译期间,已经将这三个字面量合成了一个。这样做实际上是一种优化,避免了创建多余的字符串对象,也没有发生字符串拼接问题。

위 내용은 Java의 문자열 문자열에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.