|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 import java.lang.annotation.*; |
|
25 import java.lang.reflect.*; |
|
26 import java.util.Arrays; |
|
27 |
|
28 /* |
|
29 * @test |
|
30 * @bug 8054307 |
|
31 * @summary Tests correctness of string related intrinsics and C2 optimizations. |
|
32 * @run main/timeout=240 TestStringIntrinsics |
|
33 */ |
|
34 public class TestStringIntrinsics { |
|
35 |
|
36 public enum Operation { |
|
37 ARR_EQUALS_B, ARR_EQUALS_C, EQUALS, COMPARE_TO, INDEX_OF, INDEX_OF_CON_U, INDEX_OF_CON_L, |
|
38 INDEX_OF_CON_UL, CONCAT, CONCAT_C, CONCAT_I, CONCAT_M, INDEX_OF_CHAR |
|
39 } |
|
40 |
|
41 @Retention(RetentionPolicy.RUNTIME) |
|
42 @Target(ElementType.METHOD) |
|
43 @interface Test { |
|
44 Operation op(); |
|
45 String constString() default ""; |
|
46 String[] inStrings() default {}; |
|
47 char[] inChars() default {}; |
|
48 int[] inInts() default {}; |
|
49 String[] outStrings() default {}; |
|
50 } |
|
51 |
|
52 public static void main(String[] args) throws Exception { |
|
53 new TestStringIntrinsics().run(); |
|
54 } |
|
55 |
|
56 public void run() throws Exception { |
|
57 // Build latin1 and UTF16 strings |
|
58 StringBuilder latin1Builder = new StringBuilder(); |
|
59 for (int i = 0; i <= 255; ++i) { |
|
60 latin1Builder.append((char) i); |
|
61 } |
|
62 String latin1 = latin1Builder.toString(); |
|
63 StringBuilder utf16Builder = new StringBuilder(); |
|
64 for (int i = 0; i <= 10000; ++i) { |
|
65 utf16Builder.append((char) i); |
|
66 } |
|
67 String utf16 = utf16Builder.toString(); |
|
68 |
|
69 // Invoke test methods |
|
70 for (Method m : TestStringIntrinsics.class.getMethods()) { |
|
71 if (m.isAnnotationPresent(Test.class)) { |
|
72 System.out.print("Checking " + m.getName() + "... "); |
|
73 Operation op = m.getAnnotation(Test.class).op(); |
|
74 Test antn = m.getAnnotation(Test.class); |
|
75 if (isStringConcatTest(op)) { |
|
76 checkStringConcat(op, m, antn); |
|
77 } else { |
|
78 checkIntrinsics(op, m, latin1, utf16, antn); |
|
79 } |
|
80 System.out.println("Done."); |
|
81 } |
|
82 } |
|
83 } |
|
84 |
|
85 private boolean isStringConcatTest(Operation op) { |
|
86 return op == Operation.CONCAT || |
|
87 op == Operation.CONCAT_C || |
|
88 op == Operation.CONCAT_I || |
|
89 op == Operation.CONCAT_M; |
|
90 } |
|
91 |
|
92 /** |
|
93 * Checks correctness of the String.equals, String.compareTo and String.indexOf intrinsics. |
|
94 * -XX:SpecialStringEquals |
|
95 * -XX:SpecialStringCompareTo |
|
96 * -XX:SpecialStringIndexOf |
|
97 */ |
|
98 private void checkIntrinsics(Operation op, Method m, String latin1, String utf16, Test antn) throws Exception { |
|
99 for (int i = 0; i < 50_000; ++i) { |
|
100 // Copy and permute latin1 and UTF16 string |
|
101 char[] arrL = latin1.toCharArray(); |
|
102 int indexL = i % arrL.length; |
|
103 int mod = (arrL.length - arrL[indexL]); |
|
104 int incL = i % ((mod != 0) ? mod : 1); |
|
105 arrL[indexL] = (char) ((int) arrL[indexL] + incL); |
|
106 String latin1Copy = String.valueOf(arrL); |
|
107 |
|
108 char[] arrU = utf16.toCharArray(); |
|
109 int indexU = i % arrU.length; |
|
110 mod = (arrU.length - arrU[indexU]); |
|
111 int incU = i % ((mod != 0) ? mod : 1); |
|
112 arrU[indexU] = (char) ((int) arrU[indexU] + incU); |
|
113 String utf16Copy = String.valueOf(arrU); |
|
114 |
|
115 switch (op) { |
|
116 case ARR_EQUALS_B: |
|
117 invokeAndCheck(m, (incL == 0), latin1.getBytes("ISO-8859-1"), latin1Copy.getBytes("ISO-8859-1")); |
|
118 invokeAndCheck(m, true, new byte[] {1, 2, 3}, new byte[] {1, 2, 3}); |
|
119 invokeAndCheck(m, true, new byte[] {1}, new byte[] {1}); |
|
120 invokeAndCheck(m, true, new byte[] {}, new byte[] {}); |
|
121 break; |
|
122 case ARR_EQUALS_C: |
|
123 invokeAndCheck(m, (incU == 0), utf16.toCharArray(), arrU); |
|
124 break; |
|
125 case EQUALS: |
|
126 invokeAndCheck(m, (incL == 0), latin1, latin1Copy); |
|
127 invokeAndCheck(m, false, latin1, ""); |
|
128 invokeAndCheck(m, false, "", latin1); |
|
129 |
|
130 invokeAndCheck(m, (incU == 0), utf16, utf16Copy); |
|
131 invokeAndCheck(m, false, utf16, ""); |
|
132 invokeAndCheck(m, false, "", utf16); |
|
133 |
|
134 invokeAndCheck(m, false, latin1, utf16); |
|
135 break; |
|
136 case COMPARE_TO: |
|
137 invokeAndCheck(m, -incL, latin1, latin1Copy); |
|
138 invokeAndCheck(m, latin1.length(), latin1, ""); |
|
139 |
|
140 invokeAndCheck(m, -incU, utf16, utf16Copy); |
|
141 invokeAndCheck(m, utf16.length(), utf16, ""); |
|
142 |
|
143 // Cross coder |
|
144 char cL = latin1.charAt(indexL); |
|
145 char cU = utf16.charAt(indexU); |
|
146 invokeAndCheck(m, cL - cU, latin1, latin1.replace(cL, cU)); |
|
147 invokeAndCheck(m, cU - cL, utf16, utf16.replace(cU, cL)); |
|
148 |
|
149 // Different lengths |
|
150 invokeAndCheck(m, 1, "ABCD", "ABC"); |
|
151 invokeAndCheck(m, -1, "\uff21\uff22\uff23", "\uff21\uff22\uff23\uff24"); |
|
152 invokeAndCheck(m, 1, "ABC\uff24", "ABC"); |
|
153 invokeAndCheck(m, 3, "ABC\uff24\uff25\uff26", "ABC"); |
|
154 invokeAndCheck(m, -1, "ABC","ABC\uff24"); |
|
155 invokeAndCheck(m, -3, "ABC","ABC\uff24\uff25\uff26"); |
|
156 break; |
|
157 case INDEX_OF: |
|
158 invokeAndCheck(m, indexL, latin1, latin1.substring(indexL), (indexL > 42) ? 42 : 0); |
|
159 invokeAndCheck(m, 0, latin1, "", 0); |
|
160 |
|
161 invokeAndCheck(m, indexU, utf16, utf16.substring(indexU), (indexU > 42) ? 42 : 0); |
|
162 invokeAndCheck(m, 0, utf16, "", 0); |
|
163 |
|
164 // Cross coder |
|
165 invokeAndCheck(m, -1, latin1.substring(0, indexL), utf16.substring(indexU), (indexL > 42) ? 42 : 0); |
|
166 // Skip latin1 chars in utf16 string |
|
167 int start = 256; |
|
168 int end = indexU > start ? indexU : start; |
|
169 invokeAndCheck(m, end-start, utf16.substring(start, end) + latin1.substring(indexL), latin1.substring(indexL), 0); |
|
170 break; |
|
171 case INDEX_OF_CON_L: |
|
172 invokeAndCheck(m, antn.constString(), latin1); |
|
173 break; |
|
174 case INDEX_OF_CON_U: |
|
175 invokeAndCheck(m, antn.constString(), utf16); |
|
176 break; |
|
177 case INDEX_OF_CON_UL: |
|
178 invokeAndCheck(m, antn.constString(), utf16); |
|
179 break; |
|
180 case INDEX_OF_CHAR: |
|
181 invokeAndCheck(m, 7, "abcdefg\uD800\uDC00", 65536, 0); |
|
182 invokeAndCheck(m, -1, "abcdefg\uD800\uDC01", 65536, 0); |
|
183 invokeAndCheck(m, -1, "abcdefg\uD800", 65536, 0); |
|
184 invokeAndCheck(m, 3, "abc\u0107", 263, 0); |
|
185 invokeAndCheck(m, -1, "abc\u0108", 263, 0); |
|
186 invokeAndCheck(m, 7, "abcdefg\u0107", 263, 0); |
|
187 invokeAndCheck(m, 7, "abcdefg\u0107", 263, -1); |
|
188 invokeAndCheck(m, 0, "\u0107", 263, 0); |
|
189 break; |
|
190 default: |
|
191 throw new RuntimeException("Unexpected operation."); |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 /** |
|
197 * Checks correctness of the C2 string concatenation optimization. |
|
198 * -XX:OptimizeStringConcat |
|
199 */ |
|
200 private void checkStringConcat(Operation op, Method m, Test antn) throws Exception { |
|
201 for (int i = 0; i < 50_000; ++i) { |
|
202 String[] result = antn.outStrings(); |
|
203 switch(op) { |
|
204 case CONCAT: |
|
205 String[] strs = antn.inStrings(); |
|
206 for (int j = 0; j < strs.length; ++j) { |
|
207 invokeAndCheck(m, result[j], strs[j]); |
|
208 } |
|
209 break; |
|
210 case CONCAT_C: |
|
211 char[] ch = antn.inChars(); |
|
212 for (int j = 0; j < ch.length; ++j) { |
|
213 invokeAndCheck(m, result[j], ch[j]); |
|
214 } |
|
215 break; |
|
216 case CONCAT_I: |
|
217 int[] k = antn.inInts(); |
|
218 for (int j = 0; j < k.length; ++j) { |
|
219 invokeAndCheck(m, result[j], k[j]); |
|
220 } |
|
221 break; |
|
222 case CONCAT_M: |
|
223 strs = antn.inStrings(); |
|
224 ch = antn.inChars(); |
|
225 k = antn.inInts(); |
|
226 for (int j = 0; j < strs.length; ++j) { |
|
227 invokeAndCheck(m, result[j], strs[j], ch[j], k[j]); |
|
228 } |
|
229 break; |
|
230 default: |
|
231 throw new RuntimeException("Unexpected operation."); |
|
232 } |
|
233 } |
|
234 } |
|
235 |
|
236 /** |
|
237 * Invokes method 'm' by passing arguments 'args' and checks if the |
|
238 * returned value equals 'expectedResult'. |
|
239 */ |
|
240 private void invokeAndCheck(Method m, Object expectedResult, Object... args) throws Exception { |
|
241 Object result = m.invoke(null, args); |
|
242 if (!result.equals(expectedResult)) { |
|
243 // System.out.println("Expected:"); |
|
244 // System.out.println(expectedResult); |
|
245 // System.out.println("Returned:"); |
|
246 // System.out.println(result); |
|
247 throw new RuntimeException("Result of '" + m.getName() + "' not equal to expected value."); |
|
248 } |
|
249 } |
|
250 |
|
251 /* |
|
252 * Constants |
|
253 */ |
|
254 static final char charU = '\uff21'; |
|
255 static final char charL = 'A'; |
|
256 static final String emptyString = ""; |
|
257 static final String stringL = "abcdefghijklmnop"; |
|
258 static final String stringSmallL = "abc"; |
|
259 static final String stringU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"; |
|
260 static final String stringSmallU = "\u0f21\u0f22\u0f23"; |
|
261 static final int constInt = 123; |
|
262 static final int constIntNeg = -123; |
|
263 |
|
264 /* |
|
265 * Arrays.equals |
|
266 */ |
|
267 @Test(op = Operation.ARR_EQUALS_B) |
|
268 public static boolean arrayEqualsB(byte[] a, byte[] b) { |
|
269 return Arrays.equals(a, b); |
|
270 } |
|
271 |
|
272 @Test(op = Operation.ARR_EQUALS_C) |
|
273 public static boolean arrayEqualsC(char[] a, char[] b) { |
|
274 return Arrays.equals(a, b); |
|
275 } |
|
276 |
|
277 /* |
|
278 * String.equals |
|
279 */ |
|
280 @Test(op = Operation.EQUALS) |
|
281 public static boolean equals(String a, String b) { |
|
282 return a.equals(b); |
|
283 } |
|
284 |
|
285 /* |
|
286 * String.compareTo |
|
287 */ |
|
288 @Test(op = Operation.COMPARE_TO) |
|
289 public static int compareTo(String a, String b) { |
|
290 return a.compareTo(b); |
|
291 } |
|
292 |
|
293 /* |
|
294 * String.indexOf |
|
295 */ |
|
296 @Test(op = Operation.INDEX_OF) |
|
297 public static int indexOf(String a, String b, int from) { |
|
298 return a.indexOf(b, from); |
|
299 } |
|
300 |
|
301 @Test(op = Operation.INDEX_OF_CON_U, constString = stringSmallU) |
|
302 public static String indexOfConstU(String a) { |
|
303 int result = a.indexOf(stringSmallU); |
|
304 return a.substring(result, result + stringSmallU.length()); |
|
305 } |
|
306 |
|
307 @Test(op = Operation.INDEX_OF_CON_U, constString = stringU) |
|
308 public static String indexOfConstLargeU(String a) { |
|
309 int result = a.indexOf(stringU); |
|
310 return a.substring(result, result + stringU.length()); |
|
311 } |
|
312 |
|
313 @Test(op = Operation.INDEX_OF_CON_U, constString = emptyString) |
|
314 public static String indexOfConstEmptyU(String a) { |
|
315 int result = a.indexOf(emptyString); |
|
316 return a.substring(result, result + emptyString.length()); |
|
317 } |
|
318 |
|
319 @Test(op = Operation.INDEX_OF_CON_L, constString = stringSmallL) |
|
320 public static String indexOfConstL(String a) { |
|
321 int result = a.indexOf(stringSmallL); |
|
322 return a.substring(result, result + stringSmallL.length()); |
|
323 } |
|
324 |
|
325 @Test(op = Operation.INDEX_OF_CON_L, constString = stringL) |
|
326 public static String indexOfConstLargeL(String a) { |
|
327 int result = a.indexOf(stringL); |
|
328 return a.substring(result, result + stringL.length()); |
|
329 } |
|
330 |
|
331 @Test(op = Operation.INDEX_OF_CON_L, constString = emptyString) |
|
332 public static String indexOfConstEmptyL(String a) { |
|
333 int result = a.indexOf(emptyString); |
|
334 return a.substring(result, result + emptyString.length()); |
|
335 } |
|
336 |
|
337 @Test(op = Operation.INDEX_OF_CON_UL, constString = stringSmallL) |
|
338 public static String indexOfConstUL(String a) { |
|
339 int result = a.indexOf(stringSmallL); |
|
340 return a.substring(result, result + stringSmallL.length()); |
|
341 } |
|
342 |
|
343 @Test(op = Operation.INDEX_OF_CON_UL, constString = stringL) |
|
344 public static String indexOfConstLargeUL(String a) { |
|
345 int result = a.indexOf(stringL); |
|
346 return a.substring(result, result + stringL.length()); |
|
347 } |
|
348 |
|
349 @Test(op = Operation.INDEX_OF_CHAR) |
|
350 public static int indexOfChar(String a, int ch, int from) { |
|
351 return a.indexOf(ch, from); |
|
352 } |
|
353 |
|
354 /* |
|
355 * String concatenation optimization |
|
356 */ |
|
357 @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"ABC", "\uff21\uff22\uff23"}) |
|
358 public static String concatString(String a) { |
|
359 return new StringBuilder().append(a).toString(); |
|
360 } |
|
361 |
|
362 @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {""}) |
|
363 public static String concatStringEmpty(String a) { |
|
364 return new StringBuilder().toString(); |
|
365 } |
|
366 |
|
367 @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"null"}) |
|
368 public static String concatStringNull(String a) { |
|
369 return new StringBuilder().append((String)null).toString(); |
|
370 } |
|
371 |
|
372 @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"abcdefghijklmnopABCabc", "abcdefghijklmnop\uff21\uff22\uff23abc"}) |
|
373 public static String concatStringConstL(String a) { |
|
374 return new StringBuilder().append(stringL).append(a).append(stringSmallL).toString(); |
|
375 } |
|
376 |
|
377 @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"\u0f21\u0f22\u0f23ABC\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\uff21\uff22\uff23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"}) |
|
378 public static String concatStringConstU(String a) { |
|
379 return new StringBuilder().append(stringSmallU).append(a).append(stringU).toString(); |
|
380 } |
|
381 |
|
382 @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"A", "\uff21"}) |
|
383 public static String concatChar(char a) { |
|
384 return new StringBuilder().append(a).toString(); |
|
385 } |
|
386 |
|
387 @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"abcdefghijklmnopAabcA\uff21", "abcdefghijklmnop\uff21abcA\uff21"}) |
|
388 public static String concatCharConstL(char a) { |
|
389 return new StringBuilder().append(stringL).append(a).append(stringSmallL).append(charL).append(charU).toString(); |
|
390 } |
|
391 |
|
392 @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"\u0f21\u0f22\u0f23A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A", "\u0f21\u0f22\u0f23\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A"}) |
|
393 public static String concatCharConstU(char a) { |
|
394 return new StringBuilder().append(stringSmallU).append(a).append(stringU).append(charU).append(charL).toString(); |
|
395 } |
|
396 |
|
397 @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"-2147483648", "-42", "42", "2147483647"}) |
|
398 public static String concatInt(int a) { |
|
399 return new StringBuilder().append(a).toString(); |
|
400 } |
|
401 |
|
402 @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"abcdefghijklmnop-2147483648abc123-123", "abcdefghijklmnop-42abc123-123", "abcdefghijklmnop42abc123-123", "abcdefghijklmnop2147483647abc123-123"}) |
|
403 public static String concatIntConstL(int b) { |
|
404 return new StringBuilder().append(stringL).append(b).append(stringSmallL).append(constInt).append(constIntNeg).toString(); |
|
405 } |
|
406 |
|
407 @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"\u0f21\u0f22\u0f23-2147483648\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f23-42\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f2342\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f232147483647\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123"}) |
|
408 public static String concatIntConstU(int b) { |
|
409 return new StringBuilder().append(stringSmallU).append(b).append(stringU).append(constInt).append(constIntNeg).toString(); |
|
410 } |
|
411 |
|
412 @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnopA123-123"}) |
|
413 public static String concatConstL(String a) { |
|
414 return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(charL).append(constInt).append(constIntNeg).toString(); |
|
415 } |
|
416 |
|
417 @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnop\u0f21\u0f22\u0f23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A\uff21123-123"}) |
|
418 public static String concatConstU(String a) { |
|
419 return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(stringSmallU).append(stringU).append(charL).append(charU).append(constInt).append(constIntNeg).toString(); |
|
420 } |
|
421 |
|
422 @Test(op = Operation.CONCAT_M, |
|
423 inStrings = {"ABCDEFG", "ABCDEFG", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"}, |
|
424 inChars = {'A', '\uff21', 'A', '\uff21'}, |
|
425 inInts = {Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE}, |
|
426 outStrings = {"ABCDEFGA-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFGA-2147483648null", |
|
427 "ABCDEFG\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFG\uff212147483647null", |
|
428 "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648null", |
|
429 "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647null"}) |
|
430 public static String concatMixed(String a, char b, int c) { |
|
431 return new StringBuilder().append(a).append(b).append(c).append((String)null) |
|
432 .append(stringL).append(constInt).append(constIntNeg).append(charL).append(stringU).append(charU) |
|
433 .append(a).append(b).append(c).append((String)null).toString(); |
|
434 } |
|
435 } |