Java开发中的Apache Commons Lang库:StringUtils工具类详解与源代码解析
最编程
2024-08-01 20:33:37
...
在之前写了一篇关于""和null区别的文章。
下面是文章的地址:
http://www.cnblogs.com/hongten/archive/2012/11/08/java_null.html
下面看看org.apache.commons.lang.StringUtils工具类源码
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Locale;
24
25 import org.apache.commons.lang.text.StrBuilder;
26
27 /**
28 * <p>Operations on {@link java.lang.String} that are
29 * <code>null</code> safe.</p>
30 *
31 * <ul>
32 * <li><b>IsEmpty/IsBlank</b>
33 * - checks if a String contains text</li>
34 * <li><b>Trim/Strip</b>
35 * - removes leading and trailing whitespace</li>
36 * <li><b>Equals</b>
37 * - compares two strings null-safe</li>
38 * <li><b>startsWith</b>
39 * - check if a String starts with a prefix null-safe</li>
40 * <li><b>endsWith</b>
41 * - check if a String ends with a suffix null-safe</li>
42 * <li><b>IndexOf/LastIndexOf/Contains</b>
43 * - null-safe index-of checks
44 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
45 * - index-of any of a set of Strings</li>
46 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
47 * - does String contains only/none/any of these characters</li>
48 * <li><b>Substring/Left/Right/Mid</b>
49 * - null-safe substring extractions</li>
50 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
51 * - substring extraction relative to other strings</li>
52 * <li><b>Split/Join</b>
53 * - splits a String into an array of substrings and vice versa</li>
54 * <li><b>Remove/Delete</b>
55 * - removes part of a String</li>
56 * <li><b>Replace/Overlay</b>
57 * - Searches a String and replaces one String with another</li>
58 * <li><b>Chomp/Chop</b>
59 * - removes the last part of a String</li>
60 * <li><b>LeftPad/RightPad/Center/Repeat</b>
61 * - pads a String</li>
62 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
63 * - changes the case of a String</li>
64 * <li><b>CountMatches</b>
65 * - counts the number of occurrences of one String in another</li>
66 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
67 * - checks the characters in a String</li>
68 * <li><b>DefaultString</b>
69 * - protects against a null input String</li>
70 * <li><b>Reverse/ReverseDelimited</b>
71 * - reverses a String</li>
72 * <li><b>Abbreviate</b>
73 * - abbreviates a string using ellipsis</li>
74 * <li><b>Difference</b>
75 * - compares Strings and reports on their differences</li>
76 * <li><b>LevensteinDistance</b>
77 * - the number of changes needed to change one String into another</li>
78 * </ul>
79 *
80 * <p>The <code>StringUtils</code> class defines certain words related to
81 * String handling.</p>
82 *
83 * <ul>
84 * <li>null - <code>null</code></li>
85 * <li>empty - a zero-length string (<code>""</code>)</li>
86 * <li>space - the space character (<code>' '</code>, char 32)</li>
87 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
88 * <li>trim - the characters <= 32 as in {@link String#trim()}</li>
89 * </ul>
90 *
91 * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
92 * That is to say that a <code>null</code> input will return <code>null</code>.
93 * Where a <code>boolean</code> or <code>int</code> is being returned
94 * details vary by method.</p>
95 *
96 * <p>A side effect of the <code>null</code> handling is that a
97 * <code>NullPointerException</code> should be considered a bug in
98 * <code>StringUtils</code> (except for deprecated methods).</p>
99 *
100 * <p>Methods in this class give sample code to explain their operation.
101 * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
102 *
103 * <p>#ThreadSafe#</p>
104 * @see java.lang.String
105 * @author Apache Software Foundation
106 * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
107 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
108 * @author Daniel L. Rall
109 * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
110 * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
111 * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
112 * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
113 * @author Holger Krauth
114 * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
115 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
116 * @author Arun Mammen Thomas
117 * @author Gary Gregory
118 * @author Phil Steitz
119 * @author Al Chou
120 * @author Michael Davey
121 * @author Reuben Sivan
122 * @author Chris Hyzer
123 * @author Scott Johnson
124 * @since 1.0
125 * @version $Id: StringUtils.java 1058365 2011-01-13 00:04:49Z niallp $
126 */
127 //@Immutable
128 public class StringUtils {
129 // Performance testing notes (JDK 1.4, Jul03, scolebourne)
130 // Whitespace:
131 // Character.isWhitespace() is faster than WHITESPACE.indexOf()
132 // where WHITESPACE is a string of all whitespace characters
133 //
134 // Character access:
135 // String.charAt(n) versus toCharArray(), then array[n]
136 // String.charAt(n) is about 15% worse for a 10K string
137 // They are about equal for a length 50 string
138 // String.charAt(n) is about 4 times better for a length 3 string
139 // String.charAt(n) is best bet overall
140 //
141 // Append:
142 // String.concat about twice as fast as StringBuffer.append
143 // (not sure who tested this)
144
145 /**
146 * The empty String <code>""</code>.
147 * @since 2.0
148 */
149 public static final String EMPTY = "";
150
151 /**
152 * Represents a failed index search.
153 * @since 2.1
154 */
155 public static final int INDEX_NOT_FOUND = -1;
156
157 /**
158 * <p>The maximum size to which the padding constant(s) can expand.</p>
159 */
160 private static final int PAD_LIMIT = 8192;
161
162 /**
163 * <p><code>StringUtils</code> instances should NOT be constructed in
164 * standard programming. Instead, the class should be used as
165 * <code>StringUtils.trim(" foo ");</code>.</p>
166 *
167 * <p>This constructor is public to permit tools that require a JavaBean
168 * instance to operate.</p>
169 */
170 public StringUtils() {
171 super();
172 }
173
174 // Empty checks
175 //-----------------------------------------------------------------------
176 /**
177 * <p>Checks if a String is empty ("") or null.</p>
178 *
179 * <pre>
180 * StringUtils.isEmpty(null) = true
181 * StringUtils.isEmpty("") = true
182 * StringUtils.isEmpty(" ") = false
183 * StringUtils.isEmpty("bob") = false
184 * StringUtils.isEmpty(" bob ") = false
185 * </pre>
186 *
187 * <p>NOTE: This method changed in Lang version 2.0.
188 * It no longer trims the String.
189 * That functionality is available in isBlank().</p>
190 *
191 * @param str the String to check, may be null
192 * @return <code>true</code> if the String is empty or null
193 */
194 public static boolean isEmpty(String str) {
195 return str == null || str.length() == 0;
196 }
197
198 /**
199 * <p>Checks if a String is not empty ("") and not null.</p>
200 *
201 * <pre>
202 * StringUtils.isNotEmpty(null) = false
203 * StringUtils.isNotEmpty("") = false
204 * StringUtils.isNotEmpty(" ") = true
205 * StringUtils.isNotEmpty("bob") = true
206 * StringUtils.isNotEmpty(" bob ") = true
207 * </pre>
208 *
209 * @param str the String to check, may be null
210 * @return <code>true</code> if the String is not empty and not null
211 */
212 public static boolean isNotEmpty(String str) {
213 return !StringUtils.isEmpty(str);
214 }
215
216 /**
217 * <p>Checks if a String is whitespace, empty ("") or null.</p>
218 *
219 * <pre>
220 * StringUtils.isBlank(null) = true
221 * StringUtils.isBlank("") = true
222 * StringUtils.isBlank(" ") = true
223 * StringUtils.isBlank("bob") = false
224 * StringUtils.isBlank(" bob ") = false
225 * </pre>
226 *
227 * @param str the String to check, may be null
228 * @return <code>true</code> if the String is null, empty or whitespace
229 * @since 2.0
230 */
231 public static boolean isBlank(String str) {
232 int strLen;
233 if (str == null || (strLen = str.length()) == 0) {
234 return true;
235 }
236 for (int i = 0; i < strLen; i++) {
237 if ((Character.isWhitespace(str.charAt(i)) == false)) {
238 return false;
239 }
240 }
241 return true;
242 }
243
244 /**
245 * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
246 *
247 * <pre>
248 * StringUtils.isNotBlank(null) = false
249 * StringUtils.isNotBlank("") = false
250 * StringUtils.isNotBlank(" ") = false
251 * StringUtils.isNotBlank("bob") = true
252 * StringUtils.isNotBlank(" bob ") = true
253 * </pre>
254 *
255 * @param str the String to check, may be null
256 * @return <code>true</code> if the String is
257 * not empty and not null and not whitespace
258 * @since 2.0
259 */
260 public static boolean isNotBlank(String str) {
261 return !StringUtils.isBlank(str);
262 }
263
264 // Trim
265 //-----------------------------------------------------------------------
266 /**
267 * <p>Removes control characters (char <= 32) from both
268 * ends of this String, handling <code>null</code> by returning
269 * an empty String ("").</p>
270 *
271 * <pre>
272 * StringUtils.clean(null) = ""
273 * StringUtils.clean("") = ""
274 * StringUtils.clean("abc") = "abc"
275 * StringUtils.clean(" abc ") = "abc"
276 * StringUtils.clean(" ") = ""
277 * </pre>
278 *
279 * @see java.lang.String#trim()
280 * @param str the String to clean, may be null
281 * @return the trimmed text, never <code>null</code>
282 * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
283 * Method will be removed in Commons Lang 3.0.
284 */
285 public static String clean(String str) {
286 return str == null ? EMPTY : str.trim();
287 }
288
289 /**
290 * <p>Removes control characters (char <= 32) from both
291 * ends of this String, handling <code>null</code> by returning
292 * <code>null</code>.</p>
293 *
294 * <p>The String is trimmed using {@link String#trim()}.
295 * Trim removes start and end characters <= 32.
296 * To strip whitespace use {@link #strip(String)}.</p>
297 *
298 * <p>To trim your choice of characters, use the
299 * {@link #strip(String, String)} methods.</p>
300 *
301 * <pre>
302 * StringUtils.trim(null) = null
303 * StringUtils.trim("") = ""
304 * StringUtils.trim(" ") = ""
305 * StringUtils.trim("abc") = "abc"
306 * StringUtils.trim(" abc ") = "abc"
307 * </pre>
308 *
309 * @param str the String to be trimmed, may be null
310 * @return the trimmed string, <code>null</code> if null String input
311 */
312 public static String trim(String str) {
313 return str == null ? null : str.trim();
314 }
315
316 /**
317 * <p>Removes control characters (char <= 32) from both
318 * ends of this String returning <code>null</code> if the String is
319 * empty ("") after the trim or if it is <code>null</code>.
320 *
321 * <p>The String is trimmed using {@link String#trim()}.
322 * Trim removes start and end characters <= 32.
323 * To strip whitespace use {@link #stripToNull(String)}.</p>
324 *
325 * <pre>
326 * StringUtils.trimToNull(null) = null
327 * StringUtils.trimToNull("") = null
328 * StringUtils.trimToNull(" ") = null
329 * StringUtils.trimToNull("abc") = "abc"
330 * StringUtils.trimToNull(" abc ") = "abc"
331 * </pre>
332 *
333 * @param str the String to be trimmed, may be null
334 * @return the trimmed String,
335 * <code>null</code> if only chars <= 32, empty or null String input
336 * @since 2.0
337 */
338 public static String trimToNull(String str) {
339 String ts = trim(str);
340 return isEmpty(ts) ? null : ts;
341 }
342
343 /**
344 * <p>Removes control characters (char <= 32) from both
345 * ends of this String returning an empty String ("") if the String
346 * is empty ("") after the trim or if it is <code>null</code>.
347 *
348 * <p>The String is trimmed using {@link String#trim()}.
349 * Trim removes start and end characters <= 32.
350 * To strip whitespace use {@link #stripToEmpty(String)}.</p>
351 *
352 * <pre>
353 * StringUtils.trimToEmpty(null) = ""
354 * StringUtils.trimToEmpty("") = ""
355 * StringUtils.trimToEmpty(" ") = ""
356 * StringUtils.trimToEmpty("abc") = "abc"
357 * StringUtils.trimToEmpty(" abc ") = "abc"
358 * </pre>
359 *
360 * @param str the String to be trimmed, may be null
361 * @return the trimmed String, or an empty String if <code>null</code> input
362 * @since 2.0
363 */
364 public static String trimToEmpty(String str) {
365 return str == null ? EMPTY : str.trim();
366 }
367
368 // Stripping
369 //-----------------------------------------------------------------------
370 /**
371 * <p>Strips whitespace from the start and end of a String.</p>
372 *
373 * <p>This is similar to {@link #trim(String)} but removes whitespace.
374 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
375 *
376 * <p>A <code>null</code> input String returns <code>null</code>.</p>
377 *
378 * <pre>
379 * StringUtils.strip(null) = null
380 * StringUtils.strip("") = ""
381 * StringUtils.strip(" ") = ""
382 * StringUtils.strip("abc") = "abc"
383 * StringUtils.strip(" abc") = "abc"
384 * StringUtils.strip("abc ") = "abc"
385 * StringUtils.strip(" abc ") = "abc"
386 * StringUtils.strip(" ab c ") = "ab c"
387 * </pre>
388 *
389 * @param str the String to remove whitespace from, may be null
390 * @return the stripped String, <code>null</code> if null String input
391 */
392 public static String strip(String str) {
393 return strip(str, null);
394 }
395
396 /**
397 * <p>Strips whitespace from the start and end of a String returning
398 * <code>null</code> if the String is empty ("") after the strip.</p>
399 *
400 * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
401 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
402 *
403 * <pre>
404 * StringUtils.stripToNull(null) = null
405 * StringUtils.stripToNull("") = null
406 * StringUtils.stripToNull(" ") = null
407 * StringUtils.stripToNull("abc") = "abc"
408 * StringUtils.stripToNull(" abc") = "abc"
409 * StringUtils.stripToNull("abc ") = "abc"
410 * StringUtils.stripToNull(" abc ") = "abc"
411 * StringUtils.stripToNull(" ab c ") = "ab c"
412 * </pre>
413 *
414 * @param str the String to be stripped, may be null
415 * @return the stripped String,
416 * <code>null</code> if whitespace, empty or null String input
417 * @since 2.0
418 */
419 public static String stripToNull(String str) {
420 if (str == null) {
421 return null;
422 }
423 str = strip(str, null);
424 return str.length() == 0 ? null : str;
425 }
426
427 /**
428 * <p>Strips whitespace from the start and end of a String returning
429 * an empty String if <code>null</code> input.</p>
430 *
431 * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
432 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
433 *
434 * <pre>
435 * StringUtils.stripToEmpty(null) = ""
436 * StringUtils.stripToEmpty("") = ""
437 * StringUtils.stripToEmpty(" ") = ""
438 * StringUtils.stripToEmpty("abc") = "abc"
439 * StringUtils.stripToEmpty(" abc") = "abc"
440 * StringUtils.stripToEmpty("abc ") = "abc"
441 * StringUtils.stripToEmpty(" abc ") = "abc"
442 * StringUtils.stripToEmpty(" ab c ") = "ab c"
443 * </pre>
444 *
445 * @param str the String to be stripped, may be null
446 * @return the trimmed String, or an empty String if <code>null</code> input
447 * @since 2.0
448 */
449 public static String stripToEmpty(String str) {
450 return str == null ? EMPTY : strip(str, null);
451 }
452
453 /**
454 * <p>Strips any of a set of characters from the start and end of a String.
455 * This is similar to {@link String#trim()} but allows the characters
456 * to be stripped to be controlled.</p>
457 *
458 * <p>A <code>null</code> input String returns <code>null</code>.
459 * An empty string ("") input returns the empty string.</p>
460 *
461 * <p>If the stripChars String is <code>null</code>, whitespace is
462 * stripped as defined by {@link Character#isWhitespace(char)}.
463 * Alternatively use {@link #strip(String)}.</p>
464 *
465 * <pre>
466 * StringUtils.strip(null, *) = null
467 * StringUtils.strip("", *) = ""
468 * StringUtils.strip("abc", null) = "abc"
469 * StringUtils.strip(" abc", null) = "abc"
470 * StringUtils.strip("abc ", null) = "abc"
471 * StringUtils.strip(" abc ", null) = "abc"
472 * StringUtils.strip(" abcyx", "xyz") = " abc"
473 * </pre>
474 *
475 * @param str the String to remove characters from, may be null
476 * @param stripChars the characters to remove, null treated as whitespace
477 * @return the stripped String, <code>null</code> if null String input
478 */
479 public static String strip(String str, String stripChars) {
480 if (isEmpty(str)) {
481 return str;
482 }
483 str = stripStart(str, stripChars);
484 return stripEnd(str, stripChars);
485 }
486
487 /**
488 * <p>Strips any of a set of characters from the start of a String.</p>
489 *
490 * <p>A <code>null</code> input String returns <code>null</code>.
491 * An empty string ("") input returns the empty string.</p>
492 *
493 * <p>If the stripChars String is <code>null</code>, whitespace is
494 * stripped as defined by {@link Character#isWhitespace(char)}.</p>
495 *
496 * <pre>
497 * StringUtils.stripStart(null, *) = null
498 * StringUtils.stripStart("", *) = ""
499 * StringUtils.stripStart("abc", "") = "abc"
500 * StringUtils.stripStart("abc", null) = "abc"
501 * StringUtils.stripStart(" abc", null) = "abc"
502 * StringUtils.stripStart("abc ", null) = "abc "
503 * StringUtils.stripStart(" abc ", null) = "abc "
504 * StringUtils.stripStart("yxabc ", "xyz") = "abc "
505 * </pre>
506 *
507 * @param str the String to remove characters from, may be null
508 * @param stripChars the characters to remove, null treated as whitespace
509 * @return the stripped String, <code>null</code> if null String input
510 */
511 public static String stripStart(String str, String stripChars) {
512 int strLen;
513 if (str == null || (strLen = str.length()) == 0) {
514 return str;
515 }
516 int start = 0;
517 if (stripChars == null) {
518 while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
519 start++;
520 }
521 } else if (stripChars.length() == 0) {
522 return str;
523 } else {
524 while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND)) {
525 start++;
526 }
527 }
528 return str.substring(start);
529 }
530
531 /**
532 * <p>Strips any of a set of characters from the end of a String.</p>
533 *
534 * <p>A <code>null</code> input String returns <code>null</code>.
535 * An empty string ("") input returns the empty string.</p>
536 *
537 * <p>If the stripChars String is <code>null</code>, whitespace is
538 * stripped as defined by {@link Character#isWhitespace(char)}.</p>
539 *
540 * <pre>
541 * StringUtils.stripEnd(null, *) = null
542 * StringUtils.stripEnd("", *) = ""
543 * StringUtils.stripEnd("abc", "") = "abc"
544 * StringUtils.stripEnd("abc", null) = "abc"
545 * StringUtils.stripEnd(" abc", null) = " abc"
546 * StringUtils.stripEnd("abc ", null) = "abc"
547 * StringUtils.stripEnd(" abc ", null) = " abc"
548 * StringUtils.stripEnd(" abcyx", "xyz") = " abc"
549 * StringUtils.stripEnd("120.00", ".0") = "12"
550 * </pre>
551 *
552 * @param str the String to remove characters from, may be null
553 * @param stripChars the set of characters to remove, null treated as whitespace
554 * @return the stripped String, <code>null</code> if null String input
555 */
556 public static String stripEnd(String str, String stripChars) {
557 int end;
558 if (str == null || (end = str.length()) == 0) {
559 return str;
560 }
561
562 if (stripChars == null) {
563 while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
564 end--;
565 }
566 } else if (stripChars.length() == 0) {
567 return str;
568 } else {
569 while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND)) {
570 end--;
571 }
572 }
573 return str.substring(0, end);
574 }
575
576 // StripAll
577 //-----------------------------------------------------------------------
578 /**
579 * <p>Strips whitespace from the start and end of every String in an array.
580 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
581 *
582 * <p>A new array is returned each time, except for length zero.
583 * A <code>null</code> array will return <code>null</code>.
584 * An empty array will return itself.
585 * A <code>null</code> array entry will be ignored.</p>
586 *
587 * <pre>
588 * StringUtils.stripAll(null) = null
589 * StringUtils.stripAll([]) = []
590 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
591 * StringUtils.stripAll(["abc ", null]) = ["abc", null]
592 * </pre>
593 *
594 * @param strs the array to remove whitespace from, may be null
595 * @return the stripped Strings, <code>null</code> if null array input
596 */
597 public static String[] stripAll(String[] strs) {
598 return stripAll(strs, null);
599 }
600
601 /**
602 * <p>Strips any of a set of characters from the start and end of every
603 * String in an array.</p>
604 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
605 *
606 * <p>A new array is returned each time, except for length zero.
607 * A <code>null</code> array will return <code>null</code>.
608 * An empty array will return itself.
609 * A <code>null</code> array entry will be ignored.
610 * A <code>null</code> stripChars will strip whitespace as defined by
611 * {@link Character#isWhitespace(char)}.</p>
612 *
613 * <pre>
614 * StringUtils.stripAll(null, *) = null
615 * StringUtils.stripAll([], *) = []
616 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]
617 * StringUtils.stripAll(["abc ", null], null) = ["abc", null]
618 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
619 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
620 * </pre>
621 *
622 * @param strs the array to remove characters from, may be null
623 * @param stripChars the characters to remove, null treated as whitespace
624 * @return the stripped Strings, <code>null</code> if null array input
625 */
626 public static String[] stripAll(String[] strs, String stripChars) {
627 int strsLen;
628 if (strs == null || (strsLen = strs.length) == 0) {
629 return strs;
630 }
631 String[] newArr = new String[strsLen];
632 for (int i = 0; i < strsLen; i++) {
633 newArr[i] = strip(strs[i], stripChars);
634 }
635 return newArr;
636 }
637
638 // Equals
639 //-----------------------------------------------------------------------
640 /**
641 * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
642 *
643 * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
644 * references are considered to be equal. The comparison is case sensitive.</p>
645 *
646 * <pre>
647 * StringUtils.equals(null, null) = true
648 * StringUtils.equals(null, "abc") = false
649 * StringUtils.equals("abc", null) = false
650 * StringUtils.equals("abc", "abc") = true
651 * StringUtils.equals("abc", "ABC") = false
652 * </pre>
653 *
654 * @see java.lang.String#equals(Object)
655 * @param str1 the first String, may be null
656 * @param str2 the second String, may be null
657 * @return <code>true</code> if the Strings are equal, case sensitive, or
658 * both <code>null</code>
659 */
660 public static boolean equals(String str1, String str2) {
661 return str1 == null ? str2 == null : str1.equals(str2);
662 }
663
664 /**
665 * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
666 * the case.</p>
667 *
668 * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
669 * references are considered equal. Comparison is case insensitive.</p>
670 *
671 * <pre>
672 * StringUtils.equalsIgnoreCase(null, null) = true
673 * StringUtils.equalsIgnoreCase(null, "abc") = false
674 * StringUtils.equalsIgnoreCase("abc", null) = false
675 * StringUtils.equalsIgnoreCase("abc", "abc") = true
676 * StringUtils.equalsIgnoreCase("abc", "ABC") = true
677 * </pre>
678 *
679 * @see java.lang.String#equalsIgnoreCase(String)
680 * @param str1 the first String, may be null
681 * @param str2 the second String, may be null
682 * @return <code>true</code> if the Strings are equal, case insensitive, or
683 * both <code>null</code>
684 */
685 public static boolean equalsIgnoreCase(String str1, String str2) {
686 return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
687 }
688
689 // IndexOf
690 //-----------------------------------------------------------------------
691 /**
692 * <p>Finds the first index within a String, handling <code>null</code>.
693 * This method uses {@link String#indexOf(int)}.</p>
694 *
695 * <p>A <code>null</code> or empty ("") String will return <code>INDEX_NOT_FOUND (-1)</code>.</p>
696 *
697 * <pre>
698 * StringUtils.indexOf(null, *) = -1
699 * StringUtils.indexOf("", *) = -1
700 * StringUtils.indexOf("aabaabaa", 'a') = 0
701 * StringUtils.indexOf("aabaabaa", 'b') = 2
702 * </pre>
703 *
704 * @param str the String to check, may be null
705 * @param searchChar the character to find
706 * @return the first index of the search character,
707 * -1 if no match or <code>null</code> string input
708 * @since 2.0
709 */
710 public static int indexOf(String str, char searchChar) {
711 if (isEmpty(str)) {
712 return INDEX_NOT_FOUND;
713 }
714 return str.indexOf(searchChar);
715 }
716
717 /**
718 * <p>Finds the first index within a String from a start position,
719 * handling <code>null</code>.
720 * This method uses {@link String#indexOf(int, int)}.</p>
721 *
722 * <p>A <code>null</code> or empty ("") String will return <code>(INDEX_NOT_FOUND) -1</code>.
723 * A negative start position is treated as zero.
724 * A start position greater than the string length returns <code>-1</code>.</p>
725 *
726 * <pre>
727 * StringUtils.indexOf(null, *, *) = -1
728 * StringUtils.indexOf("", *, *) = -1
729 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2
730 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5
731 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1
732 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
733 * </pre>
734 *
735 * @param str the String to check, may be null
736 * @param searchChar the character to find
737 * @param startPos the start position, negative treated as zero
738 * @return the first index of the search character,
739 * -1 if no match or <code>null</code> string input
740 * @since 2.0
741 */
742 public static int indexOf(String str, char searchChar, int startPos) {
743 if (isEmpty(str)) {
744 return INDEX_NOT_FOUND;
745 }
746 return str.indexOf(searchChar, startPos);
747 }
748
749 /**
750 * <p>Finds the first index within a String, handling <code>null</code>.
751 * This method uses {@link String#indexOf(String)}.</p>
752 *
753 * <p>A <code>null</code> String will return <code>-1</code>.</p>
754 *
755 * <pre>
756 * StringUtils.indexOf(null, *) = -1
757 * StringUtils.indexOf(*, null) = -1
758 * StringUtils.indexOf("", "") = 0
759 * StringUtils.indexOf("", *) = -1 (except when * = "")
760 * StringUtils.indexOf("aabaabaa", "a") = 0
761 * StringUtils.indexOf("aabaabaa", "b") = 2
762 * StringUtils.indexOf("aabaabaa", "ab") = 1
763 * StringUtils.indexOf("aabaabaa", "") = 0
764 * </pre>
765 *
766 * @param str the String to check, may be null
767 * @param searchStr the String to find, may be null
768 * @return the first index of the search String,
769 * -1 if no match or <code>null</code> string input
770 * @since 2.0
771 */
772 public static int indexOf(String str, String searchStr) {
773 if (str == null || searchStr == null) {
774 return INDEX_NOT_FOUND;
775 }
776 return str.indexOf(searchStr);
777 }
778
779 /**
780 * <p>Finds the n-th index within a String, handling <code>null</code>.
781 * This method uses {@link String#indexOf(String)}.</p>
782 *
783 * <p>A <code>null</code> String will return <code>-1</code>.</p>
784 *
785 * <pre>
786 * StringUtils.ordinalIndexOf(null, *, *) = -1
787 * StringUtils.ordinalIndexOf(*, null, *) = -1
788 * StringUtils.ordinalIndexOf("", "", *) = 0
789 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
790 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
791 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
792 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
793 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
794 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
795 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
796 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
797 * </pre>
798 *
799 * <p>Note that 'head(String str, int n)' may be implemented as: </p>
800 *
801 * <pre>
802 * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
803 * </pre>
804 *
805 * @param str the String to check, may be null
806 * @param searchStr the String to find, may be null
807 * @param ordinal the n-th <code>searchStr</code> to find
808 * @return the n-th index of the search String,
809 * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
810 * @since 2.1
811 */
812 public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
813 return ordinalIndexOf(str, searchStr, ordinal, false);
814 }
815
816 /**
817 * <p>Finds the n-th index within a String, handling <code>null</code>.
818 * This method uses {@link String#indexOf(String)}.</p>
819 *
820 * <p>A <code>null</code> String will return <code>-1</code>.</p>
821 *
822 * @param str the String to check, may be null
823 * @param searchStr the String to find, may be null
824 * @param ordinal the n-th <code>searchStr</code> to find
825 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
826 * @return the n-th index of the search String,
827 * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
828 */
829 // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
830 private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {
831 if (str == null || searchStr == null || ordinal <= 0) {
832 return INDEX_NOT_FOUND;
833 }
834 if (searchStr.length() == 0) {
835 return lastIndex ? str.length() : 0;
836 }
837 int found = 0;
838 int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
839 do {
840 if(lastIndex) {
841 index = str.lastIndexOf(searchStr, index - 1);
842 } else {
843 index = str.indexOf(searchStr, index + 1);
844 }
845 if (index < 0) {
846 return index;
847 }
848 found++;
849 } while (found < ordinal);
850 return index;
851 }
852
853 /**
854 * <p>Finds the first index within a String, handling <code>null</code>.
855 * This method uses {@link String#indexOf(String, int)}.</p>
856 *
857 * <p>A <code>null</code> String will return <code>-1</code>.
858 * A negative start position is treated as zero.
859 * An empty ("") search String always matches.
860 * A start position greater than the string length only matches
861 * an empty search String.</p>
862 *
863 * <pre>
864 * StringUtils.indexOf(null, *, *) = -1
865 * StringUtils.indexOf(*, null, *) = -1
866 * StringUtils.indexOf("", "", 0) = 0
867 * StringUtils.indexOf("", *, 0) = -1 (except when * = "")
868 * StringUtils.indexOf("aabaabaa", "a", 0) = 0
869 * StringUtils.indexOf("aabaabaa", "b", 0) = 2
870 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
871 * StringUtils.indexOf("aabaabaa", "b", 3) = 5
872 * StringUtils.indexOf("aabaabaa", "b", 9) = -1
873 * StringUtils.indexOf("aabaabaa", "b", -1) = 2
874 * StringUtils.indexOf("aabaabaa", "", 2) = 2
875 * StringUtils.indexOf("abc", "", 9) = 3
876 * </pre>
877 *
878 * @param str the String to check, may be null
879 * @param searchStr the String to find, may be null
880 * @param startPos the start position, negative treated as zero
881 * @return the first index of the search String,
882 * -1 if no match or <code>null</code> string input
883 * @since 2.0
884 */
885 public static int indexOf(String str, String searchStr, int startPos) {
886 if (str == null || searchStr == null) {
887 return INDEX_NOT_FOUND;
888 }
889 // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
890 if (searchStr.length() == 0 && startPos >= str.length()) {
891 return str.length();
892 }
893 return str.indexOf(searchStr, startPos);
894 }
895
896 /**
897 * <p>Case in-sensitive find of the first index within a String.</p>
898 *
899 * <p>A <code>null</code> String will return <code>-1</code>.
900 * A negative start position is treated as zero.
901 * An empty ("") search String always matches.
902 * A start position greater than the string length only matches
903 * an empty search String.</p>
904 *
905 * <pre>
906 * StringUtils.indexOfIgnoreCase(null, *) = -1
907 * StringUtils.indexOfIgnoreCase(*, null) = -1
908 * StringUtils.indexOfIgnoreCase("", "") = 0
909 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0
910 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2
911 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
912 * </pre>
913 *
914 * @param str the String to check, may be null
915 * @param searchStr the String to find, may be null
916 * @return the first index of the search String,
917 * -1 if no match or <code>null</code> string input
918 * @since 2.5
919 */
920 public static int indexOfIgnoreCase(String str, String searchStr) {
921 return indexOfIgnoreCase(str, searchStr, 0);
922 }
923
924 /**
925 * <p>Case in-sensitive find of the first index within a String
926 * from the specified position.</p>
927 *
928 * <p>A <code>null</code> String will return <code>-1</code>.
929 * A negative start position is treated as zero.
930 * An empty ("") search String always matches.
931 * A start position greater than the string length only matches
932 * an empty search String.</p>
933 *
934 * <pre>
935 * StringUtils.indexOfIgnoreCase(null, *, *) = -1
936 * StringUtils.indexOfIgnoreCase(*, null, *) = -1
937 * StringUtils.indexOfIgnoreCase("", "", 0) = 0
938 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0
939 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2
940 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
941 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5
942 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1
943 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
944 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2
945 * StringUtils.indexOfIgnoreCase("abc", "", 9) = 3
946 * </pre>
947 *
948 * @param str the String to check, may be null
949 * @param searchStr the String to find, may be null
950 * @param startPos the start position, negative treated as zero
951 * @return the first index of the search String,
952 * -1 if no match or <code>null</code> string input
953 * @since 2.5
954 */
955 public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {
956 if (str == null || searchStr == null) {
957 return INDEX_NOT_FOUND;
958 }
959 if (startPos < 0) {
960 startPos = 0;
961 }
962 int endLimit = (str.length() - searchStr.length()) + 1;
963 if (startPos > endLimit) {
964 return INDEX_NOT_FOUND;
965 }
966 if (searchStr.length() == 0) {
967 return startPos;
968 }
969 for (int i = startPos; i < endLimit; i++) {
970 if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
971 return i;
972 }
973 }
974 return INDEX_NOT_FOUND;
975 }
976
977 // LastIndexOf
978 //-----------------------------------------------------------------------
979 /**
980 * <p>Finds the last index within a String, handling <code>null</code>.
981 * This method uses {@link String#lastIndexOf(int)}.</p>
982 *
983 * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
984 *
985 * <pre>
986 * StringUtils.lastIndexOf(null, *) = -1
987 * StringUtils.lastIndexOf("", *) = -1
988 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
989 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
990 * </pre>
991 *
992 * @param str the String to check, may be null
993 * @param searchChar the character to find
994 * @return the last index of the search character,
995 * -1 if no match or <code>null</code> string input
996 * @since 2.0
997 */
998 public static int lastIndexOf(String str, char searchChar) {
999 if (isEmpty(str)) {
1000 return INDEX_NOT_FOUND;
1001 }
1002 return str.lastIndexOf(searchChar);
1003 }
1004
1005 /**
1006 * <p>Finds the last index within a String from a start position,
1007 * handling <code>null</code>.
1008 * This method uses {@link String#lastIndexOf(int, int)}.</p>
1009 *
1010 * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
1011 * A negative start position returns <code>-1</code>.
1012 * A start position greater than the string length searches the whole string.</p>
1013 *
1014 * <pre>
1015 * StringUtils.lastIndexOf(null, *, *) = -1
1016 * StringUtils.lastIndexOf("", *, *) = -1
1017 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5
1018 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2
1019 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1
1020 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5
1021 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
1022 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
1023 * </pre>
1024 *
1025 * @param str the String to check, may be null
1026 * @param searchChar the character to find
1027 * @param startPos the start position
1028 * @return the last index of the search character,
1029 * -1 if no match or <code>null</code> string input
1030 * @since 2.0
1031 */
1032 public static int lastIndexOf(String str, char searchChar, int startPos) {
1033 if (isEmpty(str)) {
1034 return INDEX_NOT_FOUND;
1035 }
1036 return str.lastIndexOf(searchChar, startPos);
1037 }
1038
1039 /**
1040 * <p>Finds the last index within a String, handling <code>null</code>.
1041 * This method uses {@link String#lastIndexOf(String)}.</p>
1042 *
1043 * <p>A <code>null</code> String will return <code>-1</code>.</p>
1044 *
1045 * <pre>
1046 * StringUtils.lastIndexOf(null, *) = -1
1047 * StringUtils.lastIndexOf(*, null) = -1
1048 * StringUtils.lastIndexOf("", "") = 0
1049 * StringUtils.lastIndexOf("aabaabaa", "a") = 7
1050 * StringUtils.lastIndexOf("aabaabaa", "b") = 5
1051 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
1052 * StringUtils.lastIndexOf("aabaabaa", "") = 8
1053 * </pre>
1054 *
1055 * @param str the String to check, may be null
1056 * @param searchStr the String to find, may be null
1057 * @return the last index of the search String,
1058 * -1 if no match or <code>null</code> string input
1059 * @since 2.0
1060 */
1061 public static int lastIndexOf(String str, String searchStr) {
1062 if (str == null || searchStr == null) {
1063 return INDEX_NOT_FOUND;
1064 }
1065 return str.lastIndexOf(searchStr);
1066 }
1067
1068 /**
1069 * <p>Finds the n-th last index within a String, handling <code>null</code>.
1070 * This method uses {@link String#lastIndexOf(String)}.</p>
1071 *
1072 * <p>A <code>null</code> String will return <code>-1</code>.</p>
1073 *
1074 * <pre>
1075 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1
1076 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1
1077 * StringUtils.lastOrdinalIndexOf("", "", *) = 0
1078 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7
1079 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6
1080 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5
1081 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2
1082 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
1083 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
1084 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8
1085 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8
1086 * </pre>
1087 *
1088 * <p>Note that 'tail(String str, int n)' may be implemented as: </p>
1089 *
1090 * <pre>
1091 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
1092 * </pre>
1093 *
1094 * @param str the String to check, may be null
1095 * @param searchStr the String to find, may be null
1096 * @param ordinal the n-th last <code>searchStr</code> to find
1097 * @return the n-th last index of the search String,
1098 * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
1099 * @since 2.5
1100 */
1101 public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {
1102 return ordinalIndexOf(str, searchStr, ordinal, true);
1103 }
1104
1105 /**
1106 * <p>Finds the first index within a String, handling <code>null</code>.
1107 * This method uses {@link String#lastIndexOf(String, int)}.</p>
1108 *
1109 * <p>A <code>null</code> String will return <code>-1</code>.
1110 * A negative start position returns <code>-1</code>.
1111 * An empty ("") search String always matches unless the start position is negative.
1112 * A start position greater than the string length searches the whole string.</p>
1113 *
1114 * <pre>
1115 * StringUtils.lastIndexOf(null, *, *) = -1
1116 * StringUtils.lastIndexOf(*, null, *) = -1
1117 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7
1118 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5
1119 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
1120 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5
1121 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
1122 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
1123 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
1124 * </pre>
1125 *
1126 * @param str the String to check, may be null
1127 * @param searchStr the String to find, may be null
1128 * @param startPos the start position, negative treated as zero
1129 * @return the first index of the search String,
1130 * -1 if no match or <code>null</code> string input
1131 * @since 2.0
1132 */
1133 public static int lastIndexOf(String str, String searchStr, int startPos) {
1134 if (str == null || searchStr == null) {
1135 return INDEX_NOT_FOUND;
1136 }
1137 return str.lastIndexOf(searchStr, startPos);
1138 }
1139
1140 /**
1141 * <p>Case in-sensitive find of the last index within a String.</p>
1142 *
1143 * <p>A <code>null</code> String will return <code>-1</code>.
1144 * A negative start position returns <code>-1</code>.
1145 * An empty ("") search String always matches unless the start position is negative.
1146 * A start position greater than the string length searches the whole string.</p>
1147 *
1148 * <pre>
1149 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1
1150 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1
1151 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7
1152 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5
1153 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
1154 * </pre>
1155 *
1156 * @param str the String to check, may be null
1157 * @param searchStr the String to find, may be null
1158 * @return the first index of the search String,
1159 * -1 if no match or <code>null</code> string input
1160 * @since 2.5
1161 */
1162 public static int lastIndexOfIgnoreCase(String str, String searchStr) {
1163 if (str == null || searchStr == null) {
1164 return INDEX_NOT_FOUND;
1165 }
1166 return lastIndexOfIgnoreCase(str, searchStr, str.length());
1167 }
1168
1169 /**
1170 * <p>Case in-sensitive find of the last index within a String
1171 * from the specified position.</p>
1172 *
1173 * <p>A <code>null</code> String will return <code>-1</code>.
1174 * A negative start position returns <code>-1</code>.
1175 * An empty ("") search String always matches unless the start position is negative.
1176 * A start position greater than the string length searches the whole string.</p>
1177 *
1178 * <pre>
1179 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1
1180 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1
1181 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7
1182 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5
1183 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
1184 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5
1185 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
1186 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0
1187 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1
1188 * </pre>
1189 *
1190 * @param str the String to check, may be null
1191 * @param searchStr the String to find, may be null
1192 * @param startPos the start position
1193 * @return the first index of the search String,
1194 * -1 if no match or <code>null</code> string input
1195 * @since 2.5
1196 */
1197 public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {
1198 if (str == null || searchStr == null) {
1199 return INDEX_NOT_FOUND;
1200 }
1201 if (startPos > (str.length() - searchStr.length())) {
1202 startPos = str.length() - searchStr.length();
1203 }
1204 if (startPos < 0) {
1205 return INDEX_NOT_FOUND;
1206 }
1207 if (searchStr.length() == 0) {
1208 return startPos;
1209 }
1210
1211 for (int i = startPos; i >= 0; i--) {
1212 if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
1213 return i;
1214 }
1215 }
1216 return INDEX_NOT_FOUND;
1217 }
1218
1219 // Contains
1220 //-----------------------------------------------------------------------
1221 /**
1222 * <p>Checks if String contains a search character, handling <code>null</code>.
1223 * This method uses {@link String#indexOf(int)}.</p>
1224 *
1225 * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
1226 *
1227 * <pre>
1228 * StringUtils.contains(null, *) = false
1229 * StringUtils.contains("", *) = false
1230 * StringUtils.contains("abc", 'a') = true
1231 * StringUtils.contains("abc", 'z') = false
1232 * </pre>
1233 *
1234 * @param str the String to check, may be null
1235 * @param searchChar the character to find
1236 * @return true if the String contains the search character,
1237 * false if not or <code>null</code> string input
1238 * @since 2.0
1239 */
1240 public static boolean contains(String str, char searchChar) {
1241 if (isEmpty(str)) {
1242 return false;
1243 }
1244 return str.indexOf(searchChar) >= 0;
1245 }
1246
1247 /**
1248 * <p>Checks if String contains a search String, handling <code>null</code>.
1249 * This method uses {@link String#indexOf(String)}.</p>
1250 *
1251 * <p>A <code>null</code> String will return <code>false</code>.</p>
1252 *
1253 * <pre>
1254 * StringUtils.contains(null, *) = false
1255 * StringUtils.contains(*, null) = false
1256 * StringUtils.contains("", "") = true
1257 * StringUtils.contains("abc", "") = true
1258 * StringUtils.contains("abc", "a") = true
1259 * StringUtils.contains("abc", "z") = false
1260 * </pre>
1261 *
1262 * @param str the String to check, may be null
1263 * @param searchStr the String to find, may be null
1264 * @return true if the String contains the search String,
1265 * false if not or <code>null</code> string input
1266 * @since 2.0
1267 */
1268 public static boolean contains(String str, String searchStr) {
1269 if (str == null || searchStr == null) {
1270 return false;
1271 }
1272 return str.indexOf(searchStr) >= 0;
1273 }
1274
1275 /**
1276 * <p>Checks if String contains a search String irrespective of case,
1277 * handling <code>null</code>. Case-insensitivity is defined as by
1278 * {@link String#equalsIgnoreCase(String)}.
1279 *
1280 * <p>A <code>null</code> String will return <code>false</code>.</p>
1281 *
1282 * <pre>
1283 * StringUtils.contains(null, *) = false
1284 * StringUtils.contains(*, null) = false
1285 * StringUtils.contains("", "") = true
1286 * StringUtils.contains("abc", "") = true
1287 * StringUtils.contains("abc", "a") = true
1288 * StringUtils.contains("abc", "z") = false
1289 * StringUtils.contains("abc", "A") = true
1290 * StringUtils.contains("abc", "Z") = false
1291 * </pre>
1292 *
1293 * @param str the String to check, may be null
1294 * @param searchStr the String to find, may be null
1295 * @return true if the String contains the search String irrespective of
1296 * case or false if not or <code>null</code> string input
1297 */
1298 public static boolean containsIgnoreCase(String str, String searchStr) {
1299 if (str == null || searchStr == null) {
1300 return false;
1301 }
1302 int len = searchStr.length();
1303 int max = str.length() - len;
1304 for (int i = 0; i <= max; i++) {
1305 if (str.regionMatches(true, i, searchStr, 0, len)) {
1306 return true;
1307 }
1308 }
1309 return false;
1310 }
1311
1312 // IndexOfAny chars
1313 //-----------------------------------------------------------------------
1314 /**
1315 * <p>Search a String to find the first index of any
1316 * character in the given set of characters.</p>
1317 *
1318 * <p>A <code>null</code> String will return <code>-1</code>.
1319 * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
1320 *
1321 * <pre>
1322 * StringUtils.indexOfAny(null, *) = -1
1323 * StringUtils.indexOfAny("", *) = -1
1324 * StringUtils.indexOfAny(*, null) = -1
1325 * StringUtils.indexOfAny(*, []) = -1
1326 * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
1327 * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
1328 * StringUtils.indexOfAny("aba", ['z']) = -1
1329 * </pre>
1330 *
1331 * @param str the String to check, may be null
1332 * @param searchChars the chars to search for, may be null
1333 * @return the index of any of the chars, -1 if no match or null input
1334 * @since 2.0
1335 */
1336 public static int indexOfAny(String str, char[] searchChars) {
1337 if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
1338 return INDEX_NOT_FOUND;
1339 }
1340 int csLen = str.length();
1341 int csLast = csLen - 1;
1342 int searchLen = searchChars.length;
1343 int searchLast = searchLen - 1;
1344 for (int i = 0; i < csLen; i++) {
1345 char ch = str.charAt(i);
1346 for (int j = 0; j < searchLen; j++) {
1347 if (searchChars[j] == ch) {
1348 if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
1349 // ch is a supplementary character
1350 if (searchChars[j + 1] == str.charAt(i + 1)) {
1351 return i;
1352 }
1353 } else {
1354 return i;
1355 }
1356 }
1357 }
1358 }
1359 return INDEX_NOT_FOUND;
1360 }
1361
1362 /**
1363 * <p>Search a String to find the first index of any
1364 * character in the given set of characters.</p>
1365 *
1366 * <p>A <code>null</code> String will return <code>-1</code>.
1367 * A <code>null</code> search string will return <code>-1</code>.</p>
1368 *
1369 * <pre>
1370 * StringUtils.indexOfAny(null, *) = -1
1371 * StringUtils.indexOfAny("", *) = -1
1372 * StringUtils.indexOfAny(*, null) = -1
1373 * StringUtils.indexOfAny(*, "") = -1
1374 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
1375 * StringUtils.indexOfAny("zzabyycdxx", "by") =
推荐阅读
-
Java开发中的Apache Commons Lang库:StringUtils工具类详解与源代码解析
-
SSM三大框架基础面试题-一、Spring篇 什么是Spring框架? Spring是一种轻量级框架,提高开发人员的开发效率以及系统的可维护性。 我们一般说的Spring框架就是Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。比如Core Container中的Core组件是Spring所有组件的核心,Beans组件和Context组件是实现IOC和DI的基础,AOP组件用来实现面向切面编程。 Spring的6个特征: 核心技术:依赖注入(DI),AOP,事件(Events),资源,i18n,验证,数据绑定,类型转换,SpEL。 测试:模拟对象,TestContext框架,Spring MVC测试,WebTestClient。 数据访问:事务,DAO支持,JDBC,ORM,编组XML。 Web支持:Spring MVC和Spring WebFlux Web框架。 集成:远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。 语言:Kotlin,Groovy,动态语言。 列举一些重要的Spring模块? Spring Core:核心,可以说Spring其他所有的功能都依赖于该类库。主要提供IOC和DI功能。 Spring Aspects:该模块为与AspectJ的集成提供支持。 Spring AOP:提供面向切面的编程实现。 Spring JDBC:Java数据库连接。 Spring JMS:Java消息服务。 Spring ORM:用于支持Hibernate等ORM工具。 Spring Web:为创建Web应用程序提供支持。 Spring Test:提供了对JUnit和TestNG测试的支持。 谈谈自己对于Spring IOC和AOP的理解 IOC(Inversion Of Controll,控制反转)是一种设计思想: 在程序中手动创建对象的控制权,交由给Spring框架来管理。IOC在其他语言中也有应用,并非Spring特有。IOC容器实际上就是一个Map(key, value),Map中存放的是各种对象。 将对象之间的相互依赖关系交给IOC容器来管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。在实际项目中一个Service类可能由几百甚至上千个类作为它的底层,假如我们需要实例化这个Service,可能要每次都搞清楚这个Service所有底层类的构造函数,这可能会把人逼疯。如果利用IOC的话,你只需要配置好,然后在需要的地方引用就行了,大大增加了项目的可维护性且降低了开发难度。 Spring中的bean的作用域有哪些? 1.singleton:该bean实例为单例 2.prototype:每次请求都会创建一个新的bean实例(多例)。 3.request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。 4.session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。 5.global-session:全局session作用域,仅仅在基于Portlet的Web应用中才有意义,Spring5中已经没有了。Portlet是能够生成语义代码(例如HTML)片段的小型Java Web插件。它们基于Portlet容器,可以像Servlet一样处理HTTP请求。但是与Servlet不同,每个Portlet都有不同的会话。 Spring中的单例bean的线程安全问题了解吗? 概念用于理解:大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。 有两种常见的解决方案(用于回答的点): 1.在bean对象中尽量避免定义可变的成员变量(不太现实)。 2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal(线程本地化对象)中(推荐的一种方式)。 ThreadLocal解决多线程变量共享问题(参考博客):https://segmentfault.com/a/1190000009236777 Spring中Bean的生命周期: 1.Bean容器找到配置文件中Spring Bean的定义。 2.Bean容器利用Java Reflection API创建一个Bean的实例。 3.如果涉及到一些属性值,利用set方法设置一些属性值。 4.如果Bean实现了BeanNameAware接口,调用setBeanName方法,传入Bean的名字。 5.如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader方法,传入ClassLoader对象的实例。 6.如果Bean实现了BeanFactoryAware接口,调用setBeanClassFacotory方法,传入ClassLoader对象的实例。 7.与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。 8.如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执postProcessBeforeInitialization方法。 9.如果Bean实现了InitializingBean接口,执行afeterPropertiesSet方法。 10.如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。 11.如果有和加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization方法。 12.当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy方法。 13.当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。 Spring框架中用到了哪些设计模式? 1.工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。 2.代理设计模式:Spring AOP功能的实现。 3.单例设计模式:Spring中的bean默认都是单例的。 4.模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式。 5.包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。 6.观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。 7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、Spring MVC中也是用到了适配器模式适配Controller。 还有很多。。。。。。。 @Component和@Bean的区别是什么 1.作用对象不同。@Component注解作用于类,而@Bean注解作用于方法。 2.@Component注解通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。@Bean注解通常是在标有该注解的方法中定义产生这个bean,告诉Spring这是某个类的实例,当我需要用它的时候还给我。 3.@Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。比如当引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现。 @Configuration public class AppConfig { @Bean public TransferService transferService { return new TransferServiceImpl; } } <beans> <bean id="transferService" class="com.kk.TransferServiceImpl"/> </beans> @Bean public OneService getService(status) { case (status) { when 1: return new serviceImpl1; when 2: return new serviceImpl2; when 3: return new serviceImpl3; } } 将一个类声明为Spring的bean的注解有哪些? 声明bean的注解: @Component 组件,没有明确的角色 @Service 在业务逻辑层使用(service层) @Repository 在数据访问层使用(dao层) @Controller 在展现层使用,控制器的声明 注入bean的注解: @Autowired:由Spring提供 @Inject:由JSR-330提供 @Resource:由JSR-250提供 *扩:JSR 是 java 规范标准 Spring事务管理的方式有几种? 1.编程式事务:在代码中硬编码(不推荐使用)。 2.声明式事务:在配置文件中配置(推荐使用),分为基于XML的声明式事务和基于注解的声明式事务。 Spring事务中的隔离级别有哪几种? 在TransactionDefinition接口中定义了五个表示隔离级别的常量:ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 Spring事务中有哪几种事务传播行为? 在TransactionDefinition接口中定义了八个表示事务传播行为的常量。 支持当前事务的情况:PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。 不支持当前事务的情况:PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。 其他情况:PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。 二、SpringMVC篇 什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。 Spring MVC的工作原理了解嘛? image.png Springmvc的优点: (1)可以支持各种视图技术,而不仅仅局限于JSP; (2)与Spring框架集成(如IoC容器、AOP等); (3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。 (4) 支持各种请求资源的映射策略。 Spring MVC的主要组件? (1)前端控制器 DispatcherServlet(不需要程序员开发) 作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。 (2)处理器映射器HandlerMapping(不需要程序员开发) 作用:根据请求的URL来查找Handler (3)处理器适配器HandlerAdapter 注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。 (4)处理器Handler(需要程序员开发) (5)视图解析器 ViewResolver(不需要程序员开发) 作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view) (6)视图View(需要程序员开发jsp) View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等) springMVC和struts2的区别有哪些? (1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。 (2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。 (3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。 SpringMVC怎么样设定重定向和转发的? (1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4" (2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com" SpringMvc怎么和AJAX相互调用的? 通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 : (1)加入Jackson.jar (2)在配置文件中配置json的映射 (3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。 如何解决POST请求中文乱码问题,GET的又如何处理呢? (1)解决post请求乱码问题: 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8; <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> (2)get请求中文参数出现乱码解决方法有两个: ①修改tomcat配置文件添加编码与工程编码一致,如下: <ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> ②另外一种方法对参数进行重新编码: String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8") ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。 Spring MVC的异常处理 ? 统一异常处理: Spring MVC处理异常有3种方式: (1)使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver; (2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器; (3)使用@ExceptionHandler注解实现异常处理; 统一异常处理的博客:https://blog.csdn.net/ctwy291314/article/details/81983103 SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决? 是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写成员变量。(此题目类似于上面Spring 中 第5题 有两种解决方案) SpringMVC常用的注解有哪些? @RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。 @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。 @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。 SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代? 一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外,一般不用别的注解代替。 如果在拦截请求中,我想拦截get方式提交的方法,怎么配置? 可以在@RequestMapping注解里面加上method=RequestMethod.GET。 怎样在方法里面得到Request,或者Session? 直接在方法的形参中声明request,SpringMVC就自动把request对象传入。 如果想在拦截的方法里面得到从前台传入的参数,怎么得到? 直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。 如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象? 直接在方法中声明这个对象,SpringMVC就自动会把属性赋值到这个对象里面。 SpringMVC中函数的返回值是什么? 返回值可以有很多类型,有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的。 SpringMVC用什么对象从后台向前台传递数据的? 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以拿到数据。 怎么样把ModelMap里面的数据放入Session里面? 可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。 SpringMvc里面拦截器是怎么写的: 有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可: <!-- 配置SpringMvc的拦截器 --> <mvc:interceptors> <!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 --> <bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean> <!-- 只针对部分请求拦截 --> <mvc:interceptor> <mvc:mapping path="/modelMap.do" /> <bean class="com.zwp.action.MyHandlerInterceptorAdapter" /> </mvc:interceptor> </mvc:interceptors> 注解原理: 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池 三、Mybatis篇 什么是MyBatis? MyBatis是一个可以自定义SQL、存储过程和高级映射的持久层框架。 讲下MyBatis的缓存 MyBatis的缓存分为一级缓存和二级缓存,一级缓存放在session里面,默认就有, 二级缓存放在它的命名空间里,默认是不打开的,使用二级缓存属性类需要实现Serializable序列化接口, 可在它的映射文件中配置<cache/> Mybatis是如何进行分页的?分页插件的原理是什么? 1)Mybatis使用RowBounds对象进行分页,也可以直接编写sql实现分页,也可以使用Mybatis的分页插件。 2)分页插件的原理:实现Mybatis提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql。 举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10 简述Mybatis的插件运行原理,以及如何编写一个插件? 1)Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、 Executor这4种接口的插件,Mybatis通过动态代理, 为需要拦截的接口生成代理对象以实现接口方法拦截功能, 每当执行这4种接口对象的方法时,就会进入拦截方法, 具体就是InvocationHandler的invoke方法,当然, 只会拦截那些你指定需要拦截的方法。 2)实现Mybatis的Interceptor接口并复写intercept方法, 然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可, 记住,别忘了在配置文件中配置你编写的插件。 Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不? 1)Mybatis动态sql可以让我们在Xml映射文件内, 以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。 2)Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。 3)其执行原理为,使用OGNL从sql参数对象中计算表达式的值, 根据表达式的值动态拼接sql,以此来完成动态sql的功能。 #{}和${}的区别是什么? 1)#{}是预编译处理,${}是字符串替换。 2)Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值(有效的防止SQL注入); 3)Mybatis在处理${}时,就是把${}替换成变量的值。 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里? Hibernate属于全自动ORM映射工具, 使用Hibernate查询关联对象或者关联集合对象时, 可以根据对象关系模型直接获取,所以它是全自动的。 而Mybatis在查询关联对象或关联集合对象时, 需要手动编写sql来完成,所以,称之为半自动ORM映射工具。 Mybatis是否支持延迟加载?如果支持,它的实现原理是什么? 1)Mybatis仅支持association关联对象和collection关联集合对象的延迟加载, association指的就是一对一,collection指的就是一对多查询。 在Mybatis配置文件中, 可以配置是否启用延迟加载lazyLoadingEnabled=true|false。 2)它的原理是,使用CGLIB创建目标对象的代理对象, 当调用目标方法时,进入拦截器方法, 比如调用a.getB.getName, 拦截器invoke方法发现a.getB是null值, 那么就会单独发送事先保存好的查询关联B对象的sql, 把B查询上来,然后调用a.setB(b), 于是a的对象b属性就有值了, 接着完成a.getB.getName方法的调用。 这就是延迟加载的基本原理。 MyBatis与Hibernate有哪些不同? 1)Mybatis和hibernate不同,它不完全是一个ORM框架, 因为MyBatis需要程序员自己编写Sql语句, 不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句, 并将java对象和sql语句映射生成最终执行的sql, 最后将sql执行的结果再映射生成java对象。 2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql, 可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发, 例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁, 一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性, 如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。 3)Hibernate对象/关系映射能力强,数据库无关性好, 对于关系模型要求高的软件(例如需求固定的定制化软件) 如果用hibernate开发可以节省很多代码,提高效率。 但是Hibernate的缺点是学习门槛高,要精通门槛更高, 而且怎么设计O/R映射,在性能和对象模型之间如何权衡, 以及怎样用好Hibernate需要具有很强的经验和能力才行。 总之,按照用户的需求在有限的资源环境下只要能做出维护性、 扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 MyBatis的好处是什么? 1)MyBatis把sql语句从Java源程序中独立出来,放在单独的XML文件中编写, 给程序的维护带来了很大便利。 2)MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象, 大大简化了Java数据库编程的重复工作。 3)因为MyBatis需要程序员自己去编写sql语句, 程序员可以结合数据库自身的特点灵活控制sql语句, 因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。 简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系? Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。 在Xml映射文件中,<parameterMap>标签会被解析为ParameterMap对象, 其每个子元素会被解析为ParameterMapping对象。 <resultMap>标签会被解析为ResultMap对象, 其每个子元素会被解析为ResultMapping对象。 每一个<select>、<insert>、<update>、<delete> 标签均会被解析为MappedStatement对象, 标签内的sql会被解析为BoundSql对象。 什么是MyBatis的接口绑定,有什么好处? 接口映射就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置. 接口绑定有几种实现方式,分别是怎么实现的? 接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加 上@Select@Update等注解里面包含Sql语句来绑定, 另外一种就是通过xml里面写SQL来绑定,在这种情况下, 要指定xml映射文件里面的namespace必须为接口的全路径名. 什么情况下用注解绑定,什么情况下用xml绑定? 当Sql语句比较简单时候,用注解绑定;当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多 MyBatis实现一对一有几种方式?具体怎么操作的? 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成; 嵌套查询是先查一个表,根据这个表里面的结果的外键id, 去再另外一个表里面查询数据,也是通过association配置, 但另外一个表的查询通过select属性配置。 Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别? 能,Mybatis不仅可以执行一对一、一对多的关联查询, 还可以执行多对一,多对多的关联查询,多对一查询, 其实就是一对一查询,只需要把selectOne修改为selectList即可; 多对多查询,其实就是一对多查询,只需要把selectOne修改为selectList即可。 关联对象查询,有两种实现方式,一种是单独发送一个sql去查询关联对象, 赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用join查询, 一部分列是A对象的属性值,另外一部分列是关联对象B的属性值, 好处是只发一个sql查询,就可以把主对象和其关联对象查出来。 MyBatis里面的动态Sql是怎么设定的?用什么语法? MyBatis里面的动态Sql一般是通过if节点来实现,通过OGNL语法来实现, 但是如果要写的完整,必须配合where,trim节点,where节点是判断包含节点有 内容就插入where,否则不插入,trim节点是用来判断如果动态语句是以and 或or 开始,那么会自动把这个and或者or取掉。 Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式? 第一种是使用<resultMap>标签,逐一定义列名和对象属性名之间的映射关系。 第二种是使用sql列的别名功能,将列别名书写为对象属性名, 比如T_NAME AS NAME,对象属性名一般是name,小写, 但是列名不区分大小写,Mybatis会忽略列名大小写,