@@ -63,6 +63,10 @@ public final class String
63
63
64
64
private static final long serialVersionUID = -6849794470754667710L ;
65
65
66
+ static final boolean COMPACT_STRINGS ;
67
+ static {
68
+ COMPACT_STRINGS = true ;
69
+ }
66
70
67
71
private static final ObjectStreamField [] serialPersistentFields =
68
72
new ObjectStreamField [0 ];
@@ -79,18 +83,13 @@ public String(String original) {
79
83
}
80
84
81
85
public String (char value []) {
82
- this (value , 0 , value .length , null );
86
+ this (value , 0 , value .length );
83
87
}
84
88
85
- public String (char value [], boolean share ) {
86
- this (value , 0 , value .length , null );
87
- }
88
-
89
89
public String (char value [], int offset , int count ) {
90
90
String proxy =init (value ,offset ,count );
91
91
this .value =proxy .value ;
92
92
this .coder =proxy .coder ;
93
- this .hash =proxy .hash ;
94
93
}
95
94
96
95
private native String init (char [] value , int offset , int count );
@@ -99,7 +98,6 @@ public String(int[] codePoints, int offset, int count) {
99
98
String proxy =init (codePoints ,offset ,count );
100
99
this .value =proxy .value ;
101
100
this .coder =proxy .coder ;
102
- this .hash =proxy .hash ;
103
101
}
104
102
105
103
private native String init (int [] codePoints , int offset , int count );
@@ -119,13 +117,10 @@ public String(byte ascii[], int hibyte) {
119
117
this (ascii , hibyte , 0 , ascii .length );
120
118
}
121
119
122
-
123
-
124
120
public String (byte bytes [], int offset , int length , String charsetName ){
125
121
String proxy =init (bytes ,offset ,length ,charsetName );
126
122
this .value =proxy .value ;
127
123
this .coder =proxy .coder ;
128
- this .hash =proxy .hash ;
129
124
}
130
125
131
126
private native String init (byte bytes [], int offset , int length , String charsetName );
@@ -151,8 +146,7 @@ public String(byte x[], int offset, int length, Charset cset) {
151
146
this .coder = result .coder ;
152
147
}
153
148
154
- public String (byte bytes [], String charsetName )
155
- throws UnsupportedEncodingException {
149
+ public String (byte bytes [], String charsetName ) throws UnsupportedEncodingException {
156
150
this (bytes , 0 , bytes .length , charsetName );
157
151
}
158
152
@@ -164,42 +158,30 @@ public String(byte bytes[], int offset, int length) {
164
158
String proxy =init (bytes ,offset ,length );
165
159
this .value =proxy .value ;
166
160
this .coder =proxy .coder ;
167
- this .hash =proxy .hash ;
168
161
}
169
162
170
-
171
163
private native String init (byte bytes [], int offset , int length );
172
164
173
165
public String (byte bytes []) {
174
166
this (bytes , 0 , bytes .length );
175
167
}
176
168
177
-
178
169
public String (StringBuffer x ) {
179
170
this (x .toString ());
180
171
}
181
172
182
-
183
173
public String (StringBuilder x ) {
184
174
this .value = Arrays .copyOf (x .getValue (), x .length ());
185
175
this .coder = x .coder ;
186
176
}
187
177
188
178
String (char [] value , int off , int len , Void sig ) {
189
- if (len == 0 ) {
190
- this .value = "" .value ;
191
- this .coder = "" .coder ;
192
- } else {
193
- byte [] val = StringUTF16 .compress (value , off , len );
194
- if (val != null ) {
195
- this .value = val ;
196
- this .coder = LATIN1 ;
197
- return ;
198
- }
179
+ this (value , off , len );
180
+ }
199
181
200
- this . coder = UTF16 ;
201
- this .value = StringUTF16 . toBytes ( value , off , len ) ;
202
- }
182
+ String ( byte [] value , byte coder ) {
183
+ this .value = value ;
184
+ this . coder = coder ;
203
185
}
204
186
205
187
@ Deprecated
@@ -213,32 +195,21 @@ public int length() {
213
195
public boolean isEmpty () {
214
196
return value .length == 0 ;
215
197
}
216
- @ Override
217
- public char charAt (int index ) {
218
- if ((index < 0 ) || (index >= value .length )) {
219
- throw new StringIndexOutOfBoundsException (index );
220
- }
221
- return this .isLatin1 () ? StringLatin1 .charAt (this .value , index ) : StringUTF16 .charAt (this .value , index );
222
- }
223
198
199
+ native public char charAt (int index );
224
200
native public int codePointAt (int index );
225
201
native public int codePointBefore (int index );
226
202
native public int codePointCount (int beginIndex , int endIndex );
227
203
native public int offsetByCodePoints (int index , int codePointOffset );
228
204
native public void getChars (int srcBegin , int srcEnd , char dst [], int dstBegin );
229
- native void getChars (char dst [], int dstBegin );
230
205
231
206
@ Deprecated
232
207
native public void getBytes (int srcBegin , int srcEnd , byte dst [], int dstBegin );
233
- native public byte [] getBytes (String charsetName )
234
- throws UnsupportedEncodingException ;
208
+ native public byte [] getBytes (String charsetName ) throws UnsupportedEncodingException ;
235
209
236
210
public byte [] getBytes (Charset x ){
237
- // No Charset model.
238
- if (x == null ){
239
- throw new NullPointerException ();
240
- }
241
- return StringCoding .encode (x , this .coder , this .value );
211
+ if (x == null ) throw new NullPointerException ();
212
+ return StringCoding .encode (x , coder (), value );
242
213
}
243
214
244
215
native public byte [] getBytes ();
@@ -251,6 +222,26 @@ public boolean contentEquals(StringBuffer stringBuffer){
251
222
}
252
223
}
253
224
225
+ private boolean nonSyncContentEquals (AbstractStringBuilder abstractStringBuilder ) {
226
+ int len = length ();
227
+ if (len != abstractStringBuilder .length ()) {
228
+ return false ;
229
+ }
230
+ byte v1 [] = value ;
231
+ byte v2 [] = abstractStringBuilder .getValue ();
232
+ if (coder () == abstractStringBuilder .getCoder ()) {
233
+ int n = v1 .length ;
234
+ for (int i = 0 ; i < n ; i ++) {
235
+ if (v1 [i ] != v2 [i ]) {
236
+ return false ;
237
+ }
238
+ }
239
+ } else {
240
+ return isLatin1 () && StringUTF16 .contentEquals (v1 , v2 , len );
241
+ }
242
+ return true ;
243
+ }
244
+
254
245
native static boolean equals0 (char [] a , char [] b , int len );
255
246
256
247
/**
@@ -262,21 +253,28 @@ public boolean contentEquals (CharSequence charSequence){
262
253
return false ;
263
254
}
264
255
265
- // that should be the common case ( String)
266
- if (charSequence . equals ( this )) {
267
- return true ;
256
+ // cs is a String
257
+ if (charSequence instanceof String ) {
258
+ return equals ( charSequence ) ;
268
259
}
269
260
270
- // we can do that natively, too
261
+ // cs is a StringBuffer, or StringBuilder
271
262
if (charSequence instanceof AbstractStringBuilder ) {
272
- byte [] val = ((AbstractStringBuilder ) charSequence ).getValue ();
273
- byte coder = ((AbstractStringBuilder ) charSequence ).getCoder ();
274
- assert coder == UTF16 : "Currently only UTF16 is supported for String comparision with an instance of type AbstractStringBuilder" ;
275
- return StringUTF16 .contentEquals (this .value , val , this .length ());
263
+ if (charSequence instanceof StringBuffer ) {
264
+ synchronized (charSequence ) {
265
+ return nonSyncContentEquals ((AbstractStringBuilder ) charSequence );
266
+ }
267
+ } else {
268
+ return nonSyncContentEquals ((AbstractStringBuilder ) charSequence );
269
+ }
276
270
}
277
271
278
272
// generic CharSequence - expensive
279
273
int n = charSequence .length ();
274
+ if (n != length ()) {
275
+ return false ;
276
+ }
277
+
280
278
byte [] val = this .value ;
281
279
if (isLatin1 ()) {
282
280
for (int i = 0 ; i < n ; i ++) {
@@ -401,6 +399,10 @@ public static String valueOf(char character) {
401
399
native public static String valueOf (double d );
402
400
public native String intern ();
403
401
402
+ byte coder () {
403
+ return COMPACT_STRINGS ? coder : UTF16 ;
404
+ }
405
+
404
406
private boolean isLatin1 () {
405
407
return this .coder == LATIN1 ;
406
408
}
0 commit comments