1. 문자열 소개, 공통 방법 소스 코드 분석
2. 문자열 상수 풀 분석
일반적인 방법
동등합니다
손질
바꾸다
콘서트
나뉘다
STARTSWITH 및 ENDSWITH
서브 스트링
touppercase () 및 tolowercase ()
비교
문자열 소개
문자열 클래스는 Final에 의해 수정되므로 문자열 객체는 불변이 아니며 동시 프로그램은 불변성을 선호합니다. 문자열 클래스는 직렬화 가능, 비슷한 및 숯 분리 인터페이스를 구현합니다.
코드로 시작하십시오.
public void StringTest () {문자열 a = "a"+"b"+1; 문자열 b = "ab1"; System.out.println (a == B);}결과가 무엇인지 맞춰보세요? 당신의 결론이 사실이라면. 좋아, 다른 코드를 가지고합시다.
public void StringTest () {문자열 a = 새 문자열 ( "ab1"); 문자열 b = "ab1"; System.out.println (a == B);}결과는 무엇입니까? 정답은 거짓입니다.
컴파일러에서 코드가 어떻게 컴파일되는지 살펴 보겠습니다
// 첫 번째 코드 public void StringTest () {문자열 a = "ab1"; 문자열 b = "ab1"; System.out.println (a == B);} // 두 번째 코드 public void StringTest () {문자열 a1 = new String ( "ab1"); 문자열 b = "ab1"; System.out.println (a1 == b);}다시 말해, 컴파일러가 "a"+"b"+1 및 "ab1"의 효과가 동일하다는 것을 발견했기 때문에 컴파일 기간 동안 첫 번째 코드 조각이 최적화되었으며, 그것들은 모두 불변으로 구성되어 있음을 발견했습니다. 그러나 왜 그들의 기억이 동일합니까? 여전히 관심이 있다면 문자열 클래스의 중요한 소스 코드를 살펴 보겠습니다.
소스 코드
1. 문자열 속성
문자열 클래스에는 스트링을 저장할 불변의 숯 배열이 포함되어 있으며 int 변수 해시는 계산 된 해시 값을 저장하는 데 사용됩니다.
/** 값은 문자 저장에 사용됩니다. */private final char value [];/** 문자열의 해시 코드*/private int hash; // 기본적으로 0/** 상호 운용성을 위해 JDK 1.0.2의 SerialversionUid 사용*/개인 정적 최종 최종 SerialversionUid = -684979447075467710L;
2. 문자열 생성자
// 매개 변수가없는 생성자는 일반적으로 쓸모가 없습니다. 값은 불변의 공개 문자열 () {this.value = new char [0];}이기 때문에 매개 변수는 String type public String (String Original) {this.value = ordigine.value; this.hash = original.hash;} // 매개 변수는 char 어레이입니다. java.utils 패키지의 배열 클래스를 사용하여 공개 문자열 (char value []) {this.value = arrays.copyof (value, value.length);} // 바이트 배열에서 오프셋에서 시작하여 charsetnemn의 길이의 길이를 인코딩합니다. String (byte bytes [], int offset, int length, string charsetname) {if (charsetname == null) 새 nullpointerexception ( "charsetname"); 체크 바운드 (바이트, 오프셋, 길이); this.value = stringCoding.decode (charsetName, 바이트, 오프셋, 길이);} // public String (byte bytes [], int 오프셋, int 길이, 문자열 charsetname) 생성자 public string (byte bytes [], Strows charsetname throws thisupportedencodingexception {);3. 문자열의 일반적인 방법
1
Boolean Equals (Object anobject) public boolean Equals (Object Anobject) {// 참조가 동일한 개체 인 경우 true (this == anobject) {return true; } // String 유형의 데이터가 문자열이 아닌 경우 (string) {string anotherstring = (string) anobject; int n = value.length; // char 배열의 길이가 같지 않은 경우 (n == anotherstring.value.length) if false를 반환합니다. {char v1 [] = value; char v2 [] = anotherstring.value; int i = 0; // 단일 문자에서 앞쪽으로 판단하면 불평등이 있으면 false를 반환합니다 (n-! = 0) {if (v1 [i]! = v2 [i]) false를 반환합니다. i ++; } // 각 문자는 동일하며 Return True Return True; }} return false;}문자열 e1 = "좋은"; 문자열 e2 = "좋은 일상"; e1.equals (e2); // false를 반환합니다
1 첫째, 동일한 객체가 참조되는지 ==, 즉 두 참조의 메모리 주소가 동일한 지 확인하십시오. 동일하면 직접적으로 반환됩니다.
2 유형이 동일한 지 여부와 동일한 데이터 유형인지 여부를 결정합니다.
3 동일한 유형을 사용하는 경우 변환 된 문자 배열의 길이는 동일합니다.
4 각 캐릭터가 뒷면에서 앞쪽으로 동일했는지 비교
판단 순서 =. 1. 메모리 주소 2. 데이터 유형 3. 문자 배열 길이 4. 단일 문자 비교
2. 비교
int compareto (String anotherstring) public int compareto (문자열 anotherstring) {// 자체 객체 len1 in1 in1 = value.length의 줄의 길이; // 비교 된 개체의 문자열의 길이 len2 = anotherstring.value.length; // 두 문자열 길이의 최소값 lim int lim = math.min (Len1, Len2); char v1 [] = 값; char v2 [] = anotherstring.value; int k = 0; // 값의 첫 번째 문자에서 최소 길이까지 LIM에 이르기까지, 문자가 같지 않으면 (객체가 동일하지 않은 문자 - 비교되는 문자) {k <lim) {char c1 = v1 [k]; char c2 = v2 [k]; if (c1! = c2) {return c1 -c2; } k ++; } // 앞면이 모두 같으면 리턴 (자체 길이 - 객체의 길이) leen1 -len2;} return return return return문자열 co1 = "hello"; 문자열 co2 = "hello"; String co3 = "hello you"; System.out.println (co1.compareto (CO2)); // 0system.out.println (co1.compareto (co3)); // -4
이 방법은 독창적으로 작성되었으며 첫 번째로 문자 크기를 판단 할 수 있습니다.
두 객체의 비교가 문자를 비교할 수있는 경우에도 여전히 같으면 비교되는 객체의 길이가 직접 반환됩니다. 두 줄의 길이가 같으면 반환은 0이므로 세 가지 상황을 영리하게 판단합니다.
3. 해시 코드
int hashcode () public int hashcode () {int h = hash; // 해시가 계산되지 않고 문자열이 비어 있지 않으면 (h == 0 && value.length> 0) {char val [] = value; // 계산 프로세스 // [0]*31^(n-1) + s [1]*31^(n-2) + ... + s [int i = 0; i <value.length; i ++) {h = 31*h + val [i]; } // 해시 할당 해시 = h; } return h;}문자열 a = "toyou"; char val [] = a.tochararray (); char c1 = 't'; char c2 = 'a'; int f = c1; int e = c2; System.out.println (e); // 97 asystem.out.println (f); // 116 tsystem.out.println (31*val [0]); // 3596System.out.println (31*C1); // 3596 // 해시 문자를 해당 int 성형으로 자동 변환 할 수 있기 때문에 해시 코드 계산
문자열 클래스는 해시 코드 메소드를 무시하고 객체의 해시 코드 메소드는 기본 호출입니다.
문자열 클래스의 해시는 다항식을 사용하여 계산됩니다. 우리는 다른 줄을 통해 동일한 해시를 완전히 얻을 수 있습니다. 따라서 두 개의 문자열 객체의 해시 코드는 동일합니다. 이는 두 문자열이 동일하다는 것을 의미하지는 않습니다.
동일한 문자열 객체의 해시 코드는 동일해야하지만 해시 코드는 동일하지만 반드시 같은 객체는 아닙니다.
4. Startswith
Boolean StartSwith (String Prefix, int toffset) public boolean startswith (String Prefix, int toffset) {char ta [] = value; int to = toffset; char pa [] = prefix.value; int po = 0; int pc = prefix.value.length; // 참고 : Toffset은 -1 >>> 근처에있을 수 있습니다. // 시작 주소가 0보다 작거나 (비교 객체의 시작 + 길이)가 자체 객체의 길이보다 큰 경우 ((toffset <0) || (toffset> value.Length -PC)) {return false; } // (-pc> = 0) {if (ta [to ++]! = pa [po ++]) {return false; }} return true;} public boolean startswith (문자열 prefix) {return startswith (prefix, 0);} public boolean endswith (string pubix) {return startswith (viodix, value.length -length-ixix.value.length);}문자열 d = "www.58fxp.com"; System.out.println (D.StartSwith ( "www")); // true system.out.println (d.endswith ( "com")); // 진실
시작 및 종료 비교는 일반적인 방법입니다. 예를 들어, 문자열이 HTTP 프로토콜에서 나온지 또는 처음에 파일이 MP3 파일인지 판단 할 때이 메소드를 사용하여 비교할 수 있습니다.
5. 개요
문자열 concat (string str) public String cocat (String str) {int otherlen = str.length (); // 추가 된 문자열이 비어 있으면 (OtherLen == 0)이면 객체 자체를 반환하십시오. } int len = value.length; char buf [] = arrays.copyof (value, len + otherlen); str.getchars (Buf, Len); 새 문자열을 반환합니다 (buf, true);}문자열 cat = "much"; 문자열 newcat = cat.concat ( "예"); // 예
Concat 방법은 또한 일반적으로 사용되는 방법 중 하나입니다. 먼저 추가 된 문자열이 비어 있는지 결정하여 새 개체를 만들 것인지 결정합니다.
1 스 플라이 싱 문자 길이가 0 인 경우 원래 문자 객체로 직접 돌아갑니다.
2 스플릿 캐릭터는 비어 있지 않으며 새 캐릭터 객체를 반환합니다.
새 객체를 생성하려면 문자 길이를 결정하십시오
6. 다시 시작하십시오
문자열 교체 (char Oldchar, char newchar) public String replare (char oldchar, char newchar) {// 이전과 새 값을 먼저 비교합니다. int i = -1; char [] val = value; / * getfield opcode를 피하십시오 * // 이전 값이 처음 나타나는 위치를 찾으십시오 (++ i <len) {if (val [i] == Oldchar) {break; }} // 해당 위치에서 끝까지 (i <len) {char buf [] = new char [len]; for (int j = 0; j <i; j ++) {buf [j] = val [j]; } while (i <len) {char c = val [i]; buf [i] = (c == Oldchar)? 신약 : C; i ++; } 새 문자열을 반환합니다 (buf, true); }}이 님을 반환하십시오;}문자열 r1 = "어떻게해야합니까?"; 문자열 r2 = r1.replace ( "do", "is"); System.out.println (r2); // 당신은 어떻습니까
이 방법에는 초기 값이 처음에 나타나는 위치를 찾는 것과 같은 영리함이 있습니다.
Replare (String Oldstr, String Newstr) 메소드는 정규식으로 판단됩니다.
7. 트림
String trim () public String trim () {int len = value.length; int st = 0; char [] val = value; / * getfield opcode를 피하십시오 * // 문자열 앞에서 공백이없는 위치를 찾으십시오 ((st <len) && (val [st] <= '')) {st ++; } // 문자열 끝에서 공백없이 위치를 찾으십시오 ((st <len) && (val [val [len-1] <= '')) {len--; } // 앞뒤에 공백이 없으면 문자열 자체를 반환합니다 ((st> 0) || (len <value.length))? 서브 스트링 (ST, LEN) : this;}문자열 t1 = "public void"; // System.out.println 앞과 이후의 한 공간 ( "t1 :"+t1.length ()); // 공간 길이 문자열 t2 = t1.trim (); System.out.println ( "t2 :"+t2.length ()); // 11 SPACE SYSTEM.out.println (T2)을 제거합니다.
8. 내부
문자열 인턴 () 공개 기본 문자열 인턴 ();
문자열 dd = new String ( "bb"). 인턴 ();
ntern 메소드는 기본 호출이며, 그 기능은 방법 영역의 상수 풀의 평등 메소드를 통해 동일한 값의 객체를 찾는 것입니다.
찾을 수 없으면 상수 풀에 공간을 열어 문자열을 저장하고 해당 문자열에 대한 참조를 반환하십시오. 그렇지 않으면 문자열 객체에 대한 참조를 직접 반환하십시오. 이미 상수 풀에 존재합니다.
새로운 방법을 위해 생성 된 캐릭터 객체를 강제하여 상수 풀이 이미 존재하는지 확인할 수 있습니다.
소개에 두 번째 코드를 넣으십시오
// string a = new String ( "ab1"); // String a = new String ( "ab1"). 인턴 ();
A가 가리키는 주소가 상수 풀에서 나오고 B가 가리키는 문자열 상수는 기본적 으로이 방법을 호출하므로 A와 B는 동일한 주소 공간을 가리 킵니다.
int hash32 () 개인 과도 int hash32 = 0; int hash32 () {int h = hash32; if (0 == h) {// hash32에서 무해한 데이터 레이스. h = sun.misc.hashing.murmur3_32 (hashing_seed, value, 0, value.length); // h = (0! = h)를 반복하지 않도록 결과가 0이 아닌지 확인하십시오. H : 1; HASH32 = H; } return h;}JDK1.7에서 문자열 클래스가 키로 사용되는 경우 해시 관련 컬렉션 클래스는 더 이상 해시 코드 메소드를 사용하지 않지만 해시 32 메소드를 사용합니다.
이 방법은 시스템의 현재 시간, 문자열 클래스 주소, 시스템 클래스 주소 등을 해시 시드를 계산하는 요소로 사용합니다. 해시 시드를 통해 해시 시드를 통해 32 비트 int 값을 얻습니다.
public int longth () {return value.length;} public string toString () {return this;} public boolean isempty () {return value.length == 0;} public char charat (int index) {if ((index <0) || (index> = value.length)) {wash new stringindexOfBoundSexception (index); } 반환 값 [index];}위는 몇 가지 간단한 일반적인 방법입니다.
요약
문자열 객체는 불변 유형입니다. 리턴 유형의 문자열 메소드 문자열이 반환 될 때마다 새 문자열 객체를 반환 할 때마다.
문자열 객체를 비교하는 세 가지 방법 :
== 메모리 비교 : 정확하고 간결하며 간단한 두 참조에 의해 지적 된 메모리 값을 직접 비교하십시오.
같은 문자열 값 비교 : 두 참조 된 객체의 문자 값이 동일인지 비교하십시오.
해시 코드 문자열 비교 수치 : 문자열의 수치. 참조 된 해시 코드는 동일하며 메모리는 동일하지 않으며 문자 값은 동일하지 않습니다.
문자열 상수 풀의 디자인 아이디어
1. 문자열 상수 수영장 설계의 원래 의도
각 문자열은 문자열 객체이며 문자열은 시스템 개발에 자주 사용됩니다. 다른 물체처럼 생성되고 파괴되면 프로그램의 성능에 큰 영향을 미칩니다.
성능을 향상시키고 메모리 오버 헤드를 줄이기 위해 JVM은 문자열을 인스턴스화 할 때 최적화합니다.
캐시 영역과 유사한 문자열에 대한 문자열 상수 풀이 열립니다.
문자열 상수를 만들 때 먼저 문자열 상수 풀이 존재하는지 확인하십시오.
문자열은 참조 된 인스턴스를 반환하고 존재하지 않으며 문자열을 인스턴스화하여 풀에 넣습니다.
기본 사항을 실현하십시오
이 최적화를 구현하기위한 기초는 각 문자열 상수가 최종 수정 상수이므로 상수 풀의 데이터 충돌에 대해 걱정할 필요가 없다는 것입니다.
런타임 인스턴스에 의해 생성 된 Global String Constant Pool에는 항상 풀의 각 고유 문자열 객체에 대한 참조를 유지하는 테이블이 있습니다. 즉, 문자열 상수 풀의 객체를 항상 참조하므로 상수 풀의 이러한 문자열은 가비지 수집기에 의해 수집되지 않습니다.
힙, 스택, 방법 영역
문자열 상수 풀 이해, 먼저 스택 방법 영역을보십시오.
더미
저장된 것은 개체이며 각 객체에는 해당 클래스가 포함되어 있습니다.
JVM에는 힙 영역이 하나만 있으며 모든 스레드에서 공유됩니다. 힙에는 기본 유형과 객체 참조가 없지만 객체 자체 만
물체는 쓰레기 수집기에 의해 수집되므로 크기와 수명주기를 결정할 필요가 없습니다.
스택
각 스레드에는 기본 데이터 유형 객체 및 사용자 정의 객체 참조 만 저장하는 스택 영역이 포함되어 있습니다.
각 스택의 데이터 (원시 유형 및 객체 참조)는 비공개입니다.
스택은 기본 유형 변수 영역, 실행 환경 컨텍스트 및 작동 지침 영역 (작동 지침 저장)의 세 부분으로 나뉩니다.
데이터 크기와 수명주기는 확실 하며이 데이터에 대한 기준이 없으면 데이터가 사라집니다.
방법 영역
힙과 같은 정적 영역은 모든 스레드와 공유됩니다
방법 영역에는 클래스 및 정적 변수와 같이 전체 프로그램에서 항상 고유 한 요소가 포함되어 있습니다.
문자열 상수 풀
문자열 상수 풀이 방법 영역에 존재합니다
코드 : 스택 방법 영역은 문자열을 저장합니다
문자열 str1 = "abc"; String str2 = "abc"; String str3 = "abc"; String str4 = new String ( "abc"); String str5 = new String ( "abc");
인터뷰 질문
문자열 str4 = 새 문자열 ( "ABC") 얼마나 많은 개체가 생성됩니까?
분할 : str4 =, new String (), "ABC"
새 방법을 통해 새 객체를 만들 수 있습니다. 새로운 방법은 인스턴스화 된 객체를 생성하며 이미 존재하는지 여부를 찾기 위해 상수 수영장으로 이동하지 않습니다. 새로운 객체가 인스턴스화 될 것입니다.
"ABC"각 문자열은 문자열 객체입니다. 상수 수영장에 없으면 새로운 객체가 만들어져 상수 수영장에 넣습니다. 그렇지 않으면 객체 참조가 반환됩니다.
객체 주소를 str4에 할당하고 참조를 만듭니다.
따라서 상수 풀에 "ABC"리터럴이 없으면 두 개의 객체를 만들고 그렇지 않으면 하나의 객체를 만들고 참조를 만듭니다.
문자열 str1 = 새 문자열 ( "a"+"b"); 얼마나 많은 객체가 생성됩니까? 문자열 str2 = 새 문자열 ( "ABC") + "ABC"; 얼마나 많은 객체가 생성됩니까?
Java String 소스 코드 및 String Constant Pool의 위의 포괄적 인 분석은 내가 공유하는 모든 컨텐츠입니다. 나는 당신이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.