자바 의 문자열 과 문자열 상수 탱크

8153 단어 자바 기초 지식
String 은 Final 에 의 해 수식 되 고 변 하지 않 는 디자인 의 유형 으로서 어느 정도 언어 자 체 는 개발 자가 이 를 기본 데이터 형식 으로 사용 하 기 를 원한 다 고 해 야 한다. 그러나 그 자 체 는 '큰 덩치' 의 대상 으로 만 들 고 저장 하 며 심지어 조작 하 는 것 도 힘 들 고 8 가지 내 장 된 유형 처럼 제멋대로 낭비 할 수 없다.
문자열 은 자바 언어 로 개 발 된 소프트웨어 에서 자주 대량으로 사용 되 는 것 을 피 할 수 없 으 며, 왕왕 메모리 소모의 대부호 이다.자바 자 체 는 문자열 을 구축 하고 조작 하 는 빠 르 거나 은밀 한 방식 을 제공 합 니 다. 잘못 사용 하면 불필요 한 조생석사 대상 이 메모리 파편 화 를 일 으 켜 잦 은 GC 를 만 들 고 JVM 성능 에 영향 을 주기 쉽 습 니 다.심지어 일부 String 대상 은 신세대 에 충분 한 저장 공간 을 찾 지 못 해 FullGC 를 촉발 시 켜 JVM 정지 (stop the world) 를 초래 하기 때문에 프로그래머 들 이 꺼 리 는 것 이 라 고 할 수 있다.
자바 언어 자 체 는 불변성 (immutable), 스 레 드 보안 (thread safe) 의 디자인, 상수 탱크, 보조 클래스 제공 등 방식 으로 문자열 조작 과 저장 성능 을 최적화 하려 고 하기 때문에 언어 가 제공 하 는 이러한 특성 을 배 우 는 것 이 String 프로 그래 밍 을 최적화 하 는 필수 기능 이 됩 니 다.
 문자열 의 본질
자바 에서 문자열 의 본질은 utf - 16 인 코딩 을 저장 하 는 문자 배열 의 패 키 징 입 니 다. 대상 을 대상 으로 이 문자 배열 데 이 터 를 조작 할 수 있 도록 합 니 다.우 리 는 자바 대상 이 어떤 것 을 저장 하고 있 는 지 알 아야 합 니 다. 먼저 이 대상 이 어떤 속성 을 가지 고 있 는 지, 대응 하 는 것 을 봐 야 합 니 다. 우 리 는 소스 코드 를 볼 때 해당 하 는 클래스 가 어떤 데이터 필드 (field) 를 정의 하 는 지 봐 야 합 니 다.
String 은 두 개의 영역 만 정의 합 니 다 (jdk 1.8).
    /** The value is used for character storage. */
    private final char value[];

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

설명 에서 말 한 바 와 같이 value 는 이 대상 이 저장 한 문자열 배열 이 고 가 변 적 이지 않 습 니 다. 이 참조 의 가 변 적 이지 않 은 것 도 Sring 대상 의 가 변 적 이지 않 은 기초 중 하나 입 니 다.String 대상 을 가 변 적 이지 않 은 것 으로 설계 하려 는 이 유 는 문자 배열 의 특성 과 밀접 한 관 계 를 가진다 고 생각 합 니 다. 실천 에서 우 리 는 문자열 의 조합 과 캡 처 작업 을 하기 쉽 지만 한 배열 을 만 들 고 복사 하 는 비용 이 매우 많 기 때문에 가 변 적 이지 않 고 스 레 드 안전 한 특성 을 제공 할 수 있 습 니 다.hash 는 이 대상 의 hash code 의 int 값 을 캐 시 하 는 데 사 용 됩 니 다. 캐 시 를 하 는 이 유 는 String 대상 이 구조 가 끝나 면 다시 바 꿀 수 없 기 때 문 입 니 다. hashcode () 방법 을 호출 할 때마다 원본 코드 와 같이 계산 할 필요 가 없습니다.
    * @return  a hash code value for this object.
     */
    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 류 의 모든 구조 함 수 를 살 펴 보고 모든 구조 적 매개 변 수 를 문자열 배열 로 바 꾸 어 value 에 부여 합 니 다.
2. 불가 변성 (immutable)
String 대상 의 불가 변성 은 다음 세 가 지 를 통 해 이 루어 집 니 다.
1. final 수정자 로 class 정 의 를 수식 하여 클래스 자 체 를 계승 할 수 없 게 하고 사용자 가 계승 을 통 해 기 존의 디자인 을 파괴 하지 않도록 한다.
2. final 수식 으로 저 장 된 문자 배열 변 수 를 사용 하여 이 변 수 는 대상 구조 가 완 료 된 후에 바 꿀 수 없습니다.
3. 바 텀 문자 배열 의 내용 을 수정 하려 고 하지 않 고 외부 에 수정 인 터 페 이 스 를 제공 하지 않 습 니 다.
4. 구조 와 문자 배열 복사 와 관련 된 작업 에서 심도 있 는 복 제 를 사용 합 니 다.예 를 들 어 이러한 구조 함수:
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

 Arrays. copy Of (value, value. length) 코드 를 통 해 알 수 있 듯 이 반환 값 은 새로운 구조의 문자열 배열 입 니 다.이렇게 하면 모든 String 대상 은 자신의 새로운 바 텀 데 이 터 를 가지 게 된다.
    public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

비교적 재 미 있 는 것 은 이 종류의 또 다른 구조 함수 이다.
     public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

직접 값 을 부여 하 는 방식 으로 두 개의 서로 다른 String 대상 이 같은 바 텀 문자 배열 을 공유 하여 불변성 을 파괴 한 것 같 습 니 다.그러나 두 대상 이 이 문자 배열 의 내용 을 수정 하려 고 하지 않 는 다 는 점 을 감안 하면 우 리 는 두 대상 이 모두 변 하지 않 고 저장 효율 도 높 였 다 고 볼 수 있다.그러나 이런 구조 방식 은 불필요 하 다. 디자이너 는 주석 에서 이미 설명 을 했다.
5. sub 와 split 작업
JDK 1.6 및 이전 버 전에 서 문자열 에 대한 캡 처 와 분리 작업 은 기 존 문자 배열 을 바탕 으로 오프셋 (offset) 을 사용 하여 새로운 문자열 대상 을 만 드 는 것 입 니 다. 바 텀 문자 배열 을 공유 하고 공간 을 절약 할 수 있 으 며 나 쁜 점 은 바 텀 문자 배열 의 메모리 회수 에 불리 합 니 다.JDK 1.7 이후 바 텀 배열 에 대한 복사 작업 을 사용 하여 새로운 문자 배열 로 문자열 대상 을 만 들 었 습 니 다. 이 를 통 해 1.7 의 가상 컴퓨터 가 문자열 상수 탱크 의 회수 에 적지 않 은 최적화 를 한 것 을 알 수 있 습 니 다.
3. 스 레 드 안전성
에서 thread safe 를 사용 하여 하나의 디자인 을 표현 하여 이러한 구조의 대상 이 여러 스 레 드 간 에 공유 할 수 있 고 다 중 스 레 드 문제 가 발생 하지 않도록 합 니 다.자바 공식 문서 에서 sharable 은 같은 개념 을 설명 합 니 다.완전한 불가 변성 (immutable) 자체 가 스 레 드 안전 류 디자인 의 한 방법 이기 때문에 우 리 는 String 대상 이 스 레 드 안전 하 다 고 말 합 니 다.
상수 탱크
1. 대상 풀 은 대상 을 대상 으로 프로 그래 밍 하 는 데 보편적으로 사용 되 는 기술 이다. JVM 구조 와 관리 대상 은 힘 든 일이 기 때문에 한 대상 이 일정한 중용 성 을 만족 시 키 면 매번 똑 같은 기능 (또는 equals 검증 만족) 의 새로운 대상 을 구축 하 는 것 이 아니 라 중복 이용 하 는 것 이 수지 가 맞는다.문자열 상수 탱크 는 문자열 대상 탱크 입 니 다. 문자열 대상 의 불변성 때문에 문자열 상수 탱크 라 고도 부 릅 니 다.JVM 디자이너 는 통계 실천 에서 문자열 의 중복 이 용 률 을 통 해 문자열 상수 탱크 를 설계 하기 때문에 과학적 이 어야 한다.그러나 상수 탱크 의 크기 는 제한 적 (1099) 으로 이 수 치 를 초과 하면 성능 저하 문제 가 발생 하 며 JDK 1.7 이후 통과 가능 -XX:StringTableSize=1099 。2. JDK 1.6 및 이전 버 전에 서 문자열 상수 탱크 는 Perm (영구 세대) 구역 에 저장 되 고 완전한 문자열 대상 을 저장 합 니 다.이 영역 은 독립 된 메모리 영역 으로 클래스 정보 와 방법 세 션 등 을 저장 하여 잘못 사용 하면 OutOf Memeroy Error (PermSize) 에 이상 이 생기 기 쉽다.
JDK 1.7 은 문자열 상수 풀 을 메모리 (Heap) 로 옮 기 고 상수 풀 에는 더미 에서 만 든 대상 의 참조 가 저 장 됩 니 다.
JDK 1.8 은 Perm 구역 을 직접 제거 하고 MetaSpace (메타 데이터 구역) 를 사용 하 는데 사실은 Perm 과 MetaSapce 는 모두 에서 methodarea (방법 구역) 의 구체 적 인 실현 이다.JDK 1.8 에서 문자열 상수 탱크 는 여전히 더미 에서 이 루어 지 므 로 JDK 1.8 과 다 르 지 않 을 것 입 니 다.
3. 문자열 상수 풀 에 문자열 을 추가 하 는 방법 은 두 가지 가 있 습 니 다. 하 나 는 'abc' 와 유사 한 문자열 의 글자 수 를 직접 정의 하 는 것 입 니 다. 컴 파일 러 는 컴 파일 기간 에 class 바이트 코드 에 정적 상수 풀 을 만 들 고 이 상수 들 을 넣 습 니 다.가상 컴퓨터 에서 이 바이트 코드 를 불 러 올 때, 실행 할 때 문자열 상수 풀 (동적 상수 풀) 에 이 문자열 이 존재 하지 않 으 면, 더미 에 이 문자열 대상 을 만 들 고, 이 대상 의 인용 을 풀 에 넣 습 니 다 (JDK 1.6 및 이전 에는 풀 에 직접 대상 을 만 들 었 습 니 다). 만약 풀 에 존재 한다 면, 이 대상 의 인용 을 되 돌려 줍 니 다.둘째, 호출 대상 자체 의 intern () 함 수 를 통 해 JDK 1.7 에서 이 동작 은 대상 인용 을 상수 탱크 에 넣 고 이 인용 을 되 돌려 줍 니 다. JDK 1.6 및 이전 에는 상수 탱크 에 새로운 대상 을 만 들 고 새로운 대상 의 인용 을 되 돌려 줍 니 다.
5. 문자열 의 비교
 면접 에서 자바 의 두 가지 비교 대상 을 설명 하 는 방식 인 '=' 연산 과 equals () 방법 호출 (비교 기 제외) 의 공통점 과 차이 점 은 초보 자 를 현혹 시 키 는 잘못된 설명 이다."= =" 은 대상 을 비교 하 는 방식 이 아니 라 자바 언어 자체 가 가지 고 있 는 비교 인용 값 의 연산 자 입 니 다. 우 리 는 이 연산 을 만족 시 키 는 두 대상 이 같은 대상 이 라 고 명확 하 게 말 해 야 합 니 다. 모호 하 게 같은 대상 이 라 고 말 해 서 는 안 됩 니 다.자바 의 모든 대상 은 하나의 비교 방식 만 있 습 니 다. 그것 은 Object 의 equals () 방법 을 호출 하 는 것 입 니 다.이것 은 우리 가 적어도 한 가 지 를 확정 할 수 있다 는 것 을 알 고 있 습 니 다. 프로 그래 밍 에서 '=' 연산 자 를 사용 하지 말고 equals () 방법 으로 문자열 의 동일성 을 비교 해 야 합 니 다.
그런데 왜 면접 에서 의 시험 점 은 흔히 '=' 에 대한 이해 입 니까?이것 은 문자열 의 동일성 이 아니 라 뒤에 있 는 JVM 가상 컴퓨터 가 문자열 에 대한 메모리 분배 메커니즘 을 시험 한 것 이다.위 에서 우 리 는 문자열 상수 탱크 에서 대상 을 만 드 는 두 가지 방식 을 말 했 습 니 다. 여기 서 우 리 는 new 키 워드 를 통 해 만 든 대상 은 반드시 더미 에 존재 하고 새로운 저장 공간 을 열 것 입 니 다.이 두 가 지 를 알 면 비교적 이해 하기 쉽다.
//      JDK1.8
/**                          "+"  
a、b                      ,          "abc"、"def"         */
String a = "abcdef";
String b = "abc" + "def";
//a==b    true


/**        new          ,                 ,       "xxx"、"yyy"、"zzz"                ,                           ,         "yyyzzz"  ,     */
String c = new String("xxx");
String d = new String("yyy")+new String("zzz");

/**f==d   false
   g==d   false
   f==g   true
*/
String f = "yyyzzz";
String g = "yyy"+"zzz";

6. 문자열 생 성
위의 코드 세 션 을 기반 으로 알 고 있 습 니 다.
1. new String ("xxx") 방식 으로 문자열 대상 을 만 들 지 말 아야 합 니 다. 이것 은 두 개의 대상 을 만 들 것 입 니 다. 우 리 는 가능 한 한 문자열 의 글자 수 를 직접 사용 해 야 합 니 다.
2. String b = "abc" + "def" 방식 으로 문자열 을 맞 추 지 마 십시오. 이것 은 풀 에 "abc" + "def" 두 개의 한 번 만 사용 하 는 대상 을 만 들 지만 상수 풀 에 인용 되 어 제때에 회수 할 수 없습니다.String d = new String ("yy") + new String ("zzz") 이라는 코드 는 전혀 바람 직 하지 않 고 면접 문제 에 만 존재 합 니 다.자바 에 서 는 StringBuffer (스 레 드 보안) 와 StringBuilder (비 스 레 드 보안) 두 개의 보조 클래스 가 효율 적 인 문자열 조합 방식 을 제공 하여 상기 문 제 를 피 할 수 있 습 니 다.
소결:
문 자 는 프로 그래 밍 언어 가 인류 문자 에 적응 하기 위 한 확장 이다.컴퓨터 가 처음 처럼 과학적 인 계산 도구 (예 를 들 어 주판) 라면 프로 그래 밍 계 는 문자열 과 같은 데이터 형식 이 필요 하지 않 을 수도 있 지만 대중 화 된 전자 장치 로 서 문자열 이 없어 서 는 안 된다.컴퓨터 는 오늘날 까지 계산 범 위 를 넘 어 사람들 이 정 보 를 저장 하고 전파 하 는 주류 매개체 가 되 었 다.어떻게 한 사람 을 묘사 합 니까?주민등록번호 나 학 번 하나만 으로 는 부족 하 다.한 사람의 이름, 주소, 교제 권, 취미, 교육 경험.
이상 은 필자 가 자바 문자열 에 대한 이해 입 니 다. 오류 가 있 으 면 지적 해 주 십시오.

좋은 웹페이지 즐겨찾기