string¶ÔÏóµÄ·½·¨ÓÐÄÄЩ£¬stringµÄ´æ´¢½á¹¹
chanong
|1. String ÀàÐ͸ÅÊö2. String ´æ´¢ÐéÄâ»úµÄÔËÐÐʱÄڴ棨JDK1.8 ÒÔÉ**æ±¾£© ³£Á¿³Ø´´½¨String ¶ÔÏó3. String ÀàÐ͵ÄÁ¬½Ó£¨concat ·½·¨+·ûºÅÁ¬½Ó£© 4. ×Ö·û´®±È½ÏµÄÏàµÈ·½·¨'=='ÔËËã·û£¨ÒÔÏÂÔ´Âë»ùÓÚjdk11£©
1. String ÀàÐ͸ÅÊöString ÀàÐÍÊDZíʾ×Ö·û´®ÀàÐ͵IJο¼Êý¾ÝÀàÐÍ¡£ Stringµ×²ãʹÓÃbyte[]Êý×éÀ´´æ´¢char[]Êý×é¡£ £¨JDK1.9¼°Ö®ºóµÄ°æ±¾£¬JDK1.9֮ǰµÄ°æ±¾Ê¹ÓÃcharÊý×éÀ´´æ´¢£¬µ«ÊÇΪÁ˽ÚÊ¡¿Õ¼ä£¬JDK1.9¿ªÊ¼Ê¹ÓÃbyteÊý×éÀ´´æ´¢¡££©
@Stableprivate Final byte[] value;//¶¨ÒåÒ»¸ö×Ö½ÚÊý×飬ÓÃÓÚ´æ´¢¹¹Ô캯Êý´«ÈëµÄcharÊý×é¡£ÕâÔÚÏÂÃæµÄ´úÂëÖÐʹÓᣠ12 ´ÓÉÏÃæµÄ´úÂë¿ÉÒÔ¿´³ö£¬StringÀàÐÍÊDz»¿É±äµÄ£¬ÒòΪStringÓÃÀ´´æ´¢Êý¾ÝµÄÊý×éÊÇ˽Óеġ¢×îÖյġ£
//String µÄ¹¹Ô캯Êýpublic String(char value[]) { this(value, 0, value.length, null); //µ÷ÓÃÁíÒ»¸ö¹¹Ô캯Êý¡£´úÂëÈçÏÂ} 12String(char[] value, int off, int len, Void sig) { if (len==0) { this.value=''.value; this.coder=''.coder; return; } } if (COMPACT_STRINGS) { byte[] val=StringUTF16.compress( value, off , len); if (val !=null) { this.value=val; this.coder=LATIN1; return; } } this.coder=UTF16; this.value=StringUTF16.toBytes(value, off, len );} 1234567891011121314151617 2. String ´æ´¢µÄÐéÄâ»úÔËÐÐʱÄڴ棨JDK1.8 ¼°¸ü¸ß°æ±¾£© JVM ÄÚ´æÖÐÓëString ´æ´¢Ïà¹ØµÄ½á¹¹°üÀ¨£º Ö÷Òª°üÀ¨¶ÑºÍÐéÄâ»ú¶ÑÕ»¡£
³£Á¿³ØJavaµÄ³£Á¿³ØÓÃÓÚ´æ´¢±àÒëʱȷ¶¨µÄ±àÒëÀàÎļþÖеÄÊý¾Ý¡£Õâ°üÀ¨Àà¡¢·½·¨¡¢½Ó¿ÚµÈµÄ³£Á¿£¬ÒÔ¼°×Ö·û´®³£Á¿£¬ÀýÈçString s='java'¡£µ±È»£¬ËüÊÇ¿ÉÒÔÀ©Õ¹µÄ£¬Ö´ÐÐÆ÷Éú³ÉµÄ³£Á¿Ò²Êdz£Á¿³Ø£¬ËùÒÔ¿ÉÒ԰ѳ£Á¿³Ø¿´³ÉÊÇJVMÖеÄÒ»¸öÌØÊâµÄÄÚ´æ¿Õ¼ä¡£
ÔÚ³£Á¿³ØÖÐʹÓÃStringÔÊÐí¶à¸öÒýÓÃÖ¸Ïòͬһ¸ö³£Á¿³ØÖеĶÔÏ󣬴Ӷø½ÚÊ¡´óÁ¿µÄÄÚ´æ¿Õ¼ä¿ªÏú¡£´ÓJDK1.8¿ªÊ¼£¬³£Á¿³Ø´æ´¢ÔÚJVMÔËÐÐʱÄÚ´æÖеĶÑÄÚ´æÖС£
´´½¨String¶ÔÏóÖ÷ÒªÓÐÁ½ÖÖ·½·¨£º 1. String a='abcd'; ʹÓÃÕâÖÖ´´½¨·½·¨Ê±£¬Èç¹û³£Á¿³ØÖв»´æÔÚString¶ÔÏó'abcd'£¬Ôò´´½¨µÄÁ½¸ö¶ÔÏó£ºÒ»¸ö¶ÔÏó'abcd' StringÀàÐ͵Ä'ÔÚ³£Á¿³ØÖС£³£Á¿³ØÎ»ÓÚ¶ÑÄÚ´æÖУ¬ÈçÉÏͼËùʾ¡£ÔÚÕ»Öд´½¨Ò»¸öÒýÓÃa£¬±£´æ'abcd'µÄÄÚ´æµØÖ·£¬²¢Ö¸Ïò¶ÔÏóÖеÄ'abcd'¶ÔÏó¡£³£Á¿³Ø¶ÑÕ»¾ÍÊÇÉÏͼËùʾµÄÐéÄâ»ú¶ÑÕ»¡£
Èç¹û³£Á¿³ØÖÐÒѾ´æÔÚ¡°abcd¡±¶ÔÏó£¬ÔòÖ±½Ó·µ»Ø¸Ã¶ÔÏ󣬲¢ÇÒ½öÔÚ¶ÑÕ»ÉÏ´´½¨Ö¸Ïò¸Ã¶ÔÏóµÄÒýÓÃa¡£
2. String a=new String('abcd'); ʹÓÃÕâÖÖ´´½¨·½·¨£¬Èç¹û³£Á¿³ØÖв»´æÔÚֵΪ'abcd'µÄString¶ÔÏó£¬ÔòÔÚ³£Á¿³ØÖд´½¨ÖµÎª'abcd'µÄString¶ÔÏó¡£ÂíËÕ¡£Ê×ÏÈÎÒÃÇ´´½¨Ò»¸ö³£Á¿³Ø£¬½«×Ö·û´®¶ÔÏó¸´ÖƵ½¶ÑÄÚ´æÖУ¨³£Á¿³ØÍâºÍ¶ÑÄÚ´æÖеĵØÖ·²»Í¬£©£¬²¢ÔÚÕ»ÉÏ´´½¨Ò»¸öÒýÓÃÀ´±£´æ¡®abcd¡¯µÄµØÖ·¡£ heapÖ¸µÄÊǶÔÏóµÄ¶ÑÄÚ´æ¡£×ܹ²»á´´½¨3¸ö¶ÔÏ󣬵«ÊÇÈç¹û³£Á¿³ØÖÐÒѾ´æÔÚ¶ÔÏó¡®abcd¡¯£¬ÄÇô»áÌø¹ý³£Á¿³ØÖжÔÏóµÄ´´½¨£¬×ܹ²»á´´½¨2¸ö¶ÔÏó¡£
3¡¢×Ö·û´®ÀàÐÍÆ´½Ó£º String a='a'; String b='b'; System.out.println(a.concat(b));//ͨ¹ýa¶ÔÏóµÄconcat·½·¨Á¬½Ób¶ÔÏ󣬽á¹ûΪ£º¶ÔÓÚ'ab'123£¬ÎÒÃÇ¿´Ò»ÏÂconcat·½·¨µÄÔ´Âë¡£
public String concat(String str) { int olen=str.length(); if (olen==0) { return this; } if (coder()==str.coder()) {//ʶ±ð×Ö·û´®±àÂë±àÂëÆ÷µÄ¸ñʽΪLATIN1 »òUTF16¡£Èç¹ûÁ½¸ö×Ö·û´®µÄ±àÂë¸ñʽÏàͬ£¬ÔòÎÞÐè½øÐбàÂë¸ñʽת»»¡£ byte[] val=this.value; byte[] oval=str.value; int len=val.length + oval .length;//×éºÏ×Ö·û´®µÄ³¤¶Èbyte[] buf=Arrays.copyOf(val, len ); //´´½¨Ò»¸öÐÂÊý×éÀ´´æ´¢×éºÏºóµÄ×Ö·û´®System.arraycopy (oval, 0, buf, val.length , oval.length); return new String(buf, coder); } int len=length(); byte [] buf=StringUTF16.newBytesFor(len + olen); getBytes(buf, 0, UTF16); str.getBytes( buf, len, UTF16); return new String(buf, UTF16); }12345678910111213141516171819 ´Óconcat Ô´´úÂëÀ´¿´£¬ºÜÈÝÒ׵óö½áÂÛ£¬concat ·½·¨Í¨¹ý´´½¨ÒÔÏÂÄÚÈÝÀ´´æ´¢Á½¸ö×Ö·û´®£º³¤¶ÈµÈÓÚÁ½¸ö×Ö·û´®³¤¶ÈÖ®ºÍµÄ×Ö½ÚÊý×顣Ȼºó½«Á½¸ö×Ö·û´®ÒÀ´Î·ÅÈëÒ»¸öÊý×éÖУ¬ÊµÏÖ×Ö·û´®Æ´½Ó¡£Ö®ËùÒÔʹÓÃ×Ö½ÚÊý×飬ÊÇÒòΪÉÏÃæÌáµ½ÁË£¬µ×²ãµÄStringÀàÐÍʹÓÃ×Ö½ÚÊý×éÀ´´æ´¢charÊý×飬ËùÒÔconcatʹÓÃ×Ö½ÚÊý×éÀ´´æ´¢×Ö·û´®£¬µ«ÊÇÆäËûÀàÐÍʹÓÃÊý×éʱÐèÒª½øÐÐÀàÐÍת»»¡£×¢Ò⣺concat·½·¨²»»áÐÞ¸ÄÔʼ¶ÔÏ󣬶øÊÇ·µ»ØÒ»¸öеÄString¶ÔÏó¡£
+ ·ûºÅÆ´½Ó+ ·ûºÅÆ´½ÓÖ÷Òª·ÖΪÁ½ÖÖÇé¿ö¡£×Ö·û´®±äÁ¿£¨Õ»Öд´½¨µÄÒýÓ㩲ÎÓëµÄÆ´½Ó¡¢×Ö·û´®±äÁ¿²»²ÎÓëµÄÆ´½Ó¡¢Ö»ÓÐ×Ö·û´®³£Á¿£¨³£Á¿³ØÖеÄ×Ö·û´®¶ÔÏ󣩲ÎÓëÆ´½ÓµÄÆ´½Ó¡£Óë×Ö·û´®±äÁ¿µÄÆ´½Ó£¨¶ÑÕ»Öд´½¨µÄÒýÓã©£ºÎÒÔÚÍøÉÏËÑË÷ÁËÆ´½Ó+ºÅËùÉæ¼°µÄ×Ö·û´®±äÁ¿µÄʵÏÖÔÀí¡£
ÔÚÔËÐÐʱ£¬Á½¸ö×Ö·û´®str1 ºÍstr2 µÄ´®ÁªÊ×Ïȵ÷ÓÃString.valueOf(obj)¡£Õâ¸öObjÊÇstr1£¬String.valueOf(Obj)µÄʵÏÖÊÇreturn obj==null ¡°null¡± : obj.toString()¡£½ÓÏÂÀ´£¬´´½¨Ò»¸öStringBuilder£¬µ÷ÓÃStringBuilder(str1) ¹¹Ô캯Êý£¬½«StringBuilder ³õʼ»¯Îª³¤¶Èstr1.length()+16£¬È»ºóµ÷ÓÃappend(str1)¡£È»ºó£¬Ëüµ÷ÓÃStringBuilder.append(str2) Á¬½ÓµÚ¶þ¸ö×Ö·û´®£¬²¢µ÷ÓÃStringBuilder.toString ·µ»Ø½á¹û¡£
½ÓÏÂÀ´ÎÒÃÇÐèÒª´Óµ×²ã¿´¿´ËüÃÇÊÇÈçºÎÁ¬½ÓµÄ¡£ÊäÈëÒÔÏ´úÂ룺
public class Test{ public static void main(String[] args){ String str1='111111';String str2='222222';String str=str1 + str2;System.out.println(str); }}12345678ÏÂÒ»²½½øÈëDOS ¡£ÔÚ½çÃæÖУ¬ÔÚDOS½çÃæ½øÈë¸ÃÎļþËùÔÚµÄÎļþ¼Ð£¬Ê¹ÓÃjavac Test.javaÃüÁîÉú³É×Ö½ÚÂ룬ȻºóʹÓÃjavap -verbose TestÃüÁî·´±àÒ룬Äã»á¿´µ½ÈçϽá¹û£º ¾Í´ó¹¦¸æ³ÉÁË¡£ £¨ÏÂÃæµÄ½á¹ûÖ»»á³öÏÖÔÚJDK1.9¼°ÒÔºóµÄ°æ±¾ÖУ¬JDK1.8¼°Ö®Ç°µÄ°æ±¾Çë²Î¼ûÕâÆª²©ÎÄ£ºJava×Ö·û´®+×Ö·û´®Æ´½ÓÔÀí£©
ºÜÈÝÒ׿´³öÏÂÃæÁ½ÐдúÂë¶ÔÓ¦µÄÊÇString str=str1 + str2; Óï¾ä¡£
8: invokedynamic #4, 0//InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;13: astore_312 ¶¯Ì¬Ö¸Áîinvokedynamic Ö¸Áîµ÷ÓÃmakeConcatWithConstants ·½·¨À´Á¬½Ó×Ö·û´®¡£¸Ã·½·¨Î»ÓÚjava.lang.invoke.StringConcatFactory ÀàÖС£ÏÂÃæÊÇÔ´Â룬Èç¹ûÕâ¸ö·½·¨Ã»ÓÐÎÊÌâµÄ»°£¬¿ÉÒÔ¿´µ½Ö±½Óµ÷ÓÃÁËdoStringConcat·½·¨¡£
public static CallSite makeConcatWithConstants(MethodHandles.Lookup Lookup, String name, MethodType concatType, String Recipe, Object.constants) throws StringConcatException { if (DEBUG) { System.out.println('StringConcatFactory ' + STRATEGY + ' ÔÚÕâÀïÊÇ' + concatType + ', {' + Recipe + '}, ' + Arrays.toString(constants)); } return doStringConcat(lookup, name, concatType, false, Recipe,constants);}1234567891011ÒÔÏÂÊDz¿·ÖÔ´´úÂë¡£ doStringConcat·½·¨£¬¹ý¶àÔòÊ¡ÂÔ¡£ÔÚ·µ»ØÖµÖУ¬Äú¿ÉÒÔ¿´µ½mh µ÷ÓÃasType ·½·¨À´ÊÊÓ¦ºÍ¼ìË÷MethodHandle ¶ÔÏó¡£·µ»ØÖµÂß¼¼òµ¥À´Ëµ¾ÍÊÇ·µ»Ø½á¹û¡£×Ö·û´®Á¬½ÓÊÇÔÚ´´½¨mh ¶ÔÏóʱִÐеġ£ÔÚÉú³É·½·¨ÄÚ¡£
˽Óо²Ì¬CallSite doStringConcat£¨MethodHandles.Lookup²éÕÒ£¬×Ö·û´®Ãû³Æ£¬MethodType concatType£¬booleangenerateRecipe£¬×Ö·û´®Åä·½£¬¶ÔÏó.³£Á¿£©Å׳öStringConcatException {.MethodHandle mh; if£¨CACHE_ENABLE£©{ Key key=new Key£¨className£¬ mt, rec); mh=CACHE.get(key); if (mh==null) { mh=generate(lookup, className, mt, rec); CACHE.put(key, mh); }} else { mh=generate(lookup, className, mt, rec);}return new ConstantCallSite(mh.asType(concatType));12345678910111213141516171819ÒÔÏÂÊÇgenerate·½·¨µÄÔ´Âë¡£
˽Óо²Ì¬MethodHandlegenerate£¨Lookup Lookup£¬String className£¬MethodType mt£¬Recipe Recipe£©Å׳öStringConcatException { try { switch£¨STRATEGY£©{ case BC_SB:·µ»ØBytecodeStringBuilderStrategy.generate£¨lookup£¬className£¬mt£¬Recipe£¬Mode.DEFAULT£©; case BC_SB_SIZED:·µ»ØBytecodeStringBuilderStrategy .generate(lookup, className, mt, Recipe, Mode.SIZED); case BC_SB_SIZED_EXACT: return BytecodeStringBuilderStrategy.generate(lookup, className, mt, Recipe, Mode.SIZED_EXACT); case MH_SB_SIZED: return MethodHandleStringBuilderStrategy.generate(mt, Recipe, Mode.SIZED ); case MH_SB_SIZED_EXACT: return MethodHandleStringBuilderStrategy.generate(mt, Recipe, Mode.SIZED_EXACT); case MH_INLINE_SIZED_EXACT: return MethodHandleInlineCopyStrategy.generate(mt, Recipe); default: throw new StringConcatException('Á¬½Ó²ßÂÔ' + STRATEGY + ' δʵÏÖ¡£·ñ' £© ; } } catch (Error | StringConcatException e) { //´«µÝ´íÎó»òÒÑÓеÄStringConcatException throw e; } catch (Throwable t) { new StringConcatException('Éú³ÉÆ÷ʧ°Ü', t); }}12345678910111213141516171819202122232425Å׳öÁíÒ»¸öSTRATEGY (ͨ¹ý²ßÂÔÉú³É·½·¨) ʹÓÃÖµÀ´µ÷Óø÷ÖÖ¶ÔÏóµÄÉú³É·½·¨¡£½ÓÏÂÀ´ÈÃÎÒÃÇ¿´Ò»Ï²ßÂÔÀàÐÍ¡£ÒÔÏÂÊÇÎĵµÖеÄһЩ¼òµ¥µÄÓ¢ÎÄ·Òë¡£
private enum Strategy { /** * ×Ö½ÚÂëÉú³ÉÆ÷£¬µ÷ÓÃ{@link java.lang.StringBuilder} */BC_SB, /** * ×Ö½ÚÂëÉú³ÉÆ÷£¬µ÷ÓÃ{@link java.lang.StringBuilder}; * µ«ÊÇ£¬ÐèÒª¹À¼Æ´æ´¢¿Õ¼äÈÝÁ¿¡£ */BC_SB_SIZED, /** * ×Ö½ÚÂëÉú³ÉÆ÷µ÷ÓÃ{@link java.lang.StringBuilder}; * µ«ÐèҪ׼ȷ¼ÆËãËùÐèµÄ´æ´¢¿Õ¼ä¡£ */BC_SB_SIZED_EXACT, /** * »ùÓÚMethodHandle µÄÉú³ÉÆ÷£¬×îÖÕµ÷ÓÃ{@link java.lang.StringBuilder} * ¸Ã²ßÂÔ»¹³¢ÊÔ¹À¼ÆËùÐèµÄ´æ´¢¿Õ¼ä¡£ */MH_SB_SIZED, /** * »ùÓÚMethodHandleµÄÉú³ÉÆ÷£¬×îÖÕµ÷ÓÃ{@link java.lang.StringBuilder} * ÕâÖÖ²ßÂÔ»¹ÐèÒª¾«È·¼ÆËãËùÐèµÄ´æ´¢¿Õ¼ä¡£ */MH_SB_SIZED_EXACT, /** * »ùÓÚMethodHandle µÄÉú³ÉÆ÷»ùÓÚMethodHandle µÄÉú³ÉÆ÷¸ù¾ÝÆä²ÎÊý¹¹Ôì×Ô¼ºµÄbyte[] Êý×顣׼ȷ¼ÆËãÄúÐèÒª¶àÉÙ´æ´¢¿Õ¼ä¡£ */MH_INLINE_SIZED_EXACT }1234567891011121314151617181920212223242526272829303132333435Ö÷Òª¸ù¾ÝÇé¿öʹÓò»Í¬µÄ²ßÂÔÖµ£¬Ò»¹²6ÖÖ²ßÂÔ£¬ËùÒÔ¿ÉÒÔµ÷ÓÃÊʺϵ±Ç°Çé¿öµÄÉú³É·½·¨¡£ÒÔÉÏÎåÖÖ²ßÂÔʵÏÖ¶¼ÊÇ»ùÓÚStringBuilderµÄ¡£ÏÖÔÚÎÒÃÇÒÔÉÏÃæµÄBytecodeStringBuilderStrategyµÄGenerate·½·¨ÎªÀý£¬×Ðϸ¿´¿´ÈçºÎʵÏÖ×Ö·û´®Æ´½Ó£¨¾¹ýÒ»·¬ÕÛÌÚÖÕÓÚ½øÈëÕýÌ⣩¡£Ê×ÏÈ£¬µ÷ÓÃString µÄValueOf() ·½·¨¡£
if (mode.isExact()) {/*¾«È·Ä£Ê½ÒªÇó½«ËùÓвÎÊýת»»Îª×Ö·û´®±íʾÐÎʽ£¬ÒÔ±ã¿ÉÒÔ׼ȷ¼ÆËã×Ö·û´®´óС¡£´Ë´¦²»ÄÜʹÓÃ˽ÓÐÔʼ·½·¨£¬Òò´ËÒ²±ØÐë¶ÔÆä½øÐÐת»»¡£Ëü»¹¼Ç¼ÁËת»»½á¹ûÖб£Ö¤·Ç¿ÕµÄ²ÎÊý¡£ String.valueOf ¼ì²éËüÊÇ·ñΪ¿Õ¡£Î¨Ò»µÄ¼«¶ËÇé¿öÊÇstring.valueOf(object) ·µ»Ønull ±¾Éí¡£´ËÍ⣬Èç¹û·¢Éúת»»£¬´«µÝ²ÎÊýµÄ²ÛË÷Òý½«²»µÈÓÚ×îÖյı¾µØÓ³É䡣Ψһ¿ÉÄÜË𻵵ÄÇé¿öÊǽ«2 ¸ö²ÛλµÄ³¤/Ë«¾«¶Èת»»Îª1 ¸ö²Ûλ¡£Òò´Ë£¬×ª»»²»»á¸²¸Ç´«ÈëµÄ²ÎÊý£¬´Ó¶øÔÊÐíÄú¸ú×Ù¸ü¸ÄµÄÆ«ÒÆÁ¿¡£ */int off=0; int modOff=0; for (int c=0; c arr.length; c++) { Class cl=arr[c]; if (cl==String.class) { if (off !=modOff) {mv.visitIntInsn(getLoadOpcode(cl), off);mv.visitIntInsn(ASTORE, modOff); } } else { mv.visitIntInsn(getLoadOpcode(cl), off); mv.visitMethodInsn( INVOKESTATIC, 'java/lang /String', 'valueOf', getStringValueOfDesc(cl), false ); mv.visitIntInsn(ASTORE, modOff); arr[c]=String.class;±£Ö¤NonNull[c]=cl.isPrimitive(); } off +=getParameterSize (cl); modOff +=getParameterSize(String.class); } } if (mode.isSized()) { /* ÊìϤÔÚµ÷Õû´óСģʽ£¨°üÀ¨¾«¶Èģʽ£©Ï²Ù×÷ʱStringBuilder µÄ¸½¼ÓÁ´ÓÅ»¯StringConcat ÓÐÒâÒ塣Ϊ´Ë£¬ÎÒÃÇÐèÒª¾¡¿ì½øÐпռì²é£¬¶ø²»ÊǼò»¯×·¼ÓÁ´µÄÐÎ×´¡£ */int off=0; for (RecipeElement el : Recipe.getElements()) { switch (el.getTag()) { case TAG_CONST://±£Ö¤²»Îª¿Õ£¬²»ÐèÒª¿Õ¼ì²é.break; case TAG_ARG://¿Õ¼ì²é½ö¶ÔÓÚ×Ö·û´®²ÎÊýÊDZØÐèµÄ£¬²¢ÇÒ½öµ±ÔÚǰһ½×¶Îδ½øÐÐÒþʽnull ¼ì²éʱ²ÅÐèÒª¡£Èç¹ûString Ϊnull£¬ÇëÁ¢¼´½«ÆäÌæ»»Îª¡°null¡±³£Á¿¡£ //µ±ÐÄ¡£ÕâÀïÊ¡ÂÔÁ˶ÔÏó¡£ //²»Òªµ÷ÓÃÏÂÃæµÄ.length()¡£ int ac=el.getArgPos();Class cl=arr[ac];if (cl==String.class !guaranteedNonNull[ac]) { Label l0=new Label(); mv.visitIntInsn(ALOAD, off); mv .visitJumpInsn(IFNONNULL, l0); mv.visitLdcInsn('null'); mv.visitIntInsn(ASTORE, off); mv.visitLabel(l0);}off +=getParameterSize(cl);break;default:throw new StringConcatException('Not´¦Àí±êÇ©: ' + el.getTag()); } }1234567891011121314151617181920212223242526272829303132333435363738 394041424344454647484950515253 545556575859606162636465 ½ÓÏÂÀ´£¬´´½¨Ò»¸öStringBuilder¶ÔÏó²¢Ê¹ÓÃappend·½·¨°´Ë³Ðò×·¼Ó×Ö·û´®¡£
//×¼±¸Ò»¸öStringBuilder ʵÀýmv.visitTypeInsn(NEW, 'java/lang/StringBuilder');mv.visitInsn(DUP);if (mode.isSized()) { /*Size ģʽµü´ú²ÎÊýºÍ×îÖÕ³¤¶È¡£ÔÚÑϸñģʽÏ£¬ÕâÖ»ÊÊÓÃÓÚ×Ö·û´®¡£´Ë´úÂ뽫×îÖÕ³¤¶ÈÀÛ¼Óµ½¶ÑÕ»ÉÏ¡£ */int len=0; int off=0; mv.visitInsn(ICONST_0); for (RecipeElement el : Recipe.getElements()) { switch (el.getTag()) { case TAG_CONST: len +=el.getValue () .length(); Break; case TAG_ARG: /* Èç¹û²ÎÊýÊÇ×Ö·û´®£¬Ôò¿ÉÒÔ¶ÔÆäµ÷ÓÃ.length()¡£³ß´ç/¾«È·Ä£Ê½×ª»»²ÎÊý¡£Èç¹û²ÎÊýÊÇÔʼ²ÎÊý£¬Äú¿ÉÒÔÍÆ¶ÏÆä×Ö·û´®±íʾÐÎʽµÄ´óС¡£ */Class cl=arr[el.getArgPos()]; if (cl==String.class) { mv.visitIntInsn(ALOAD, off); mv.visitMethodInsn(INVOKEVIRTUAL,'java/lang/String','length' ,'()',false ); mv.visitInsn(IADD); } else if (cl.isPrimitive()) { len +=estimateSize(cl); } off +=getParameterSize(cl);break;default: Å׳öеÄStringConcatException ('Unhandled tag: ' + el.getTag()); } } //Èç¹û³£Á¿³¤¶È·ÇÁãÔò»ìºÏif (len 0) { icont(mv, len); mv.visitInsn(IADD); } mv .visitMethodInsn( INVOKESPECIAL , 'java/lang/StringBuilder',
"", "(I)V", false );} else { mv.visitMethodInsn( INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false );}// ´Ëʱ£¬¶ÑÕ»ÉÏÓÐÒ»¸ö¿ÕµÄStringBuilder£¬ÓÃ.appendµ÷ÓÃÌî³äËü¡£{ int off = 0; for (RecipeElement el : recipe.getElements()) { String desc; switch (el.getTag()) { case TAG_CONST: mv.visitLdcInsn(el.getValue()); desc = getSBAppendDesc(String.class); break; case TAG_ARG: Class< > cl = arr[el.getArgPos()]; mv.visitVarInsn(getLoadOpcode(cl), off); off += getParameterSize(cl); desc = getSBAppendDesc(cl); break; default: throw new StringConcatException("Unhandled tag: " + el.getTag()); } mv.visitMethodInsn(//µ÷ÓÃappend·½·¨ INVOKEVIRTUAL, "java/lang/StringBuilder", "append", desc, false ); }} if (DEBUG && mode.isExact()) { /* Exactness checks compare the final StringBuilder.capacity() with a resulting String.length(). If these values disagree, that means StringBuilder had to perform storage trimming, which defeats the purpose of exact strategies. */ /* The logic for this check is as follows:Stack before: Op: (SB)dup, dup (SB, SB, SB) capacity() (int, SB, SB) swap (SB, int, SB) toString() (S, int, SB) length() (int, int, SB) if_icmpeq (SB) Note that it leaves the same StringBuilder on exit, like the one on enter. */ mv.visitInsn(DUP); mv.visitInsn(DUP); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "capacity", "()I", false ); mv.visitInsn(SWAP); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false ); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/String", "length", "()I", false ); Label l0 = new Label(); mv.visitJumpInsn(IF_ICMPEQ, l0); mv.visitTypeInsn(NEW, "java/lang/AssertionError"); mv.visitInsn(DUP); mv.visitLdcInsn("Failed exactness check"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/AssertionError", "", "(Ljava/lang/Object;)V", false); mv.visitInsn(ATHROW); mv.visitLabel(l0); }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161ÏÂÃæÊǸ÷½·¨ÖÐĩβµÄ¼¸ÐдúÂ룬Ö÷Òª¾ÍÊǵ÷ÓÃStringBuilderµÄtoString()·½·¨²¢·µ»Ø¸Ã·½·¨µÃµ½µÄ¶ÔÏó¡£ mv.visitMethodInsn(//µ÷ÓÃStringBuilderµÄtoString()·½·¨ INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);mv.visitInsn(ARETURN);mv.visitMaxs(-1, -1);mv.visitEnd();cw.visitEnd();byte[] classBytes = cw.toByteArray();try { Class< > hostClass = lookup.lookupClass(); Class< > innerClass = UNSAFE.defineAnonymousClass(hostClass, classBytes, null); UNSAFE.ensureClassInitialized(innerClass); dumpIfEnabled(innerClass.getName(), classBytes); return Lookup.IMPL_LOOKUP.findStatic(innerClass, METHOD_NAME, args);} catch (Exception e) { dumpIfEnabled(className + "$$FAILED", classBytes); throw new StringConcatException("Exception while spinning the class", e);}12345678910111213141516171819202122232425ËùÒÔ£¬×ܽáһϣ¬ÓÐ×Ö·û´®±äÁ¿²ÎÓëÆ´½ÓµÄ¹ý³Ì£ºÊ×Ïȵ÷ÓÃStringµÄValueOf·½·¨£¬È»ºóÊÇÉú³ÉÒ»¸öStringBuilder¶ÔÏó²¢½«ÓÃappend·½·¨½«Á½¸ö×Ö·û´®ÒÀ´Î¼ÓÈ룬Ȼºó·µ»ØStringBuilderµÄtoString()·½·¨¡£ Ö»ÓÐ×Ö·û´®³£Á¿(³£Á¿³ØÖеÄString¶ÔÏó)²ÎÓëµÄÆ´½Ó£ºÀýÈ磺String a=¡°ab¡±+cd;ÕâÖÖÆ´½Ó£¬ÔÚ±àÒëʱ£¬±àÒëÆ÷»á×Ô¶¯½«a±äÁ¿±àÒëΪ"abcd"ÀýÈçÒÔÏ´úÂ룺public class Test2{public static void main(String[] args){String str = ¡°12¡±+¡°34¡±;System.out.println(str);}}ÓÃÉÏÊöµÄ·½·¨Í¬Ñù²é¿´·´±àÒë´úÂë ¿ÉÒÔ¿´µ½±àÒëÆ÷Ö±½Ó½«str×Ö·û´®±àÒëΪÁË¡±1234¡°. ËÄ¡¢×Ö·û´®µÄ±È½Ïequals·½·¨StringÀàÐ͵ĶÔÏóÓиöequals·½·¨£¬ÓÃÓڱȽÏÁ½¸öString¶ÔÏóµÄÖµÊÇ·ñÏàµÈ¡£ public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) {//ÅжϱàÂë¸ñʽÊÇ·ñÏàµÈ return isLatin1() StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); //¸ù¾Ý±àÂë¸ñʽµ÷Óò»Í¬µÄequals·½·¨ } } return false;}1234567891011121314ÏÂÃæÊÇStringLatin1¶ÔÏó(ÒÔLatin1Ϊ±àÂë¸ñʽµÄString¶ÔÏó)µÄequals·½·¨ @HotSpotIntrinsicCandidatepublic static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { for (int i = 0; i < value.length; i++) { if (value[i] != other[i]) { return false; } } return true; } return false;}123456789101112È»ºóÊÇStringUTF16¶ÔÏóµÄequals·½·¨ @HotSpotIntrinsicCandidatepublic static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { int len = value.length >> 1; for (int i = 0; i < len; i++) { if (getChar(value, i) != getChar(other, i)) { return false; } } return true; } return false;}12345678910111213¿ÉÒÔ¿´³öequals·½·¨µÄʵÏÖÂß¼¾ÍÊÇͨ¹ýforÑ»·±éÀú±£´æ×Ö·û´®µÄbyteÊý×飬һλһλµØ½øÐÐÅжϡ£ "=="ÔËËã·û¡°==¡±ÔËËã·ûÓÃÓڱȽÏÁ½¸ö¶ÔÏóµÄµØÖ·ÊÇ·ñÏàµÈ¡£ÓÃÔÚ×Ö·û´®±È½Ïʱ£¬ÐèҪעÒâ"abcd"Óënew String(¡°abcd¡±)Ëù·µ»ØµÄµØÖ·Öµ²»Ïàͬ£¬¾ßÌå¿´ÉÏ·½String¶ÔÏóµÄ´´½¨¡£×¢Ò⣺ÉÏÃæÎÒÃǾßÌå·ÖÎöÁËÓÐ×Ö·û´®±äÁ¿²ÎÓëµÄÁ¬½ÓÔ¤Ë㣬×îºóµÄ¶ÔÏóÊÇÓÉStringBuilderµÄtoString()·½·¨·µ»ØµÄ£¬¶øtoString()·½·¨µ×²ãÊÇ·µ»ØµÄÊÇnew String()¶ÔÏ󣬴洢µÄµØÖ·ÊÇÔÚ¶ÑÖУ¬¶ø²»ÊÇÔÚ³£Á¿³ØÖС£ @Override@HotSpotIntrinsicCandidatepublic String toString() {//StringBuilder¶ÔÏóµÄtoString·½·¨ // Create a copy, don't share the array return isLatin1() StringLatin1.newString(value, 0, count) : StringUTF16.newString(value, 0, count);}1234567//StringLatin1¶ÔÏóµÄnewString·½·¨public static String newString(byte[] val, int index, int len) { return new String(Arrays.copyOfRange(val, index, index + len), LATIN1);}12345//StringUTF16µÄtoString·½·¨public static String newString(byte[] val, int index, int len) { if (String.COMPACT_STRINGS) { byte[] buf = compress(val, index, len); if (buf != null) { return new String(buf, LATIN1); } } int last = index + len; return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);}







