كنت مشغولاً بالتنفيذ المنطقي للمشروع في أيام الأسبوع. كان لدي بعض الوقت يوم السبت ، لذلك أخرجت نسخة إنجليزية سميكة من التفكير في جافا من خزانة الكتب وقراءة الربط الكائنات السلسلة. ارجع إلى هذا الكتاب كترجمة ، وأضف ما تفكر فيه ، واكتب هذا المقال لتسجيله.
كائن سلسلة غير قابل للتغيير
في Java ، تكون كائنات السلسلة غير قابلة للتغيير (غير قابلة للتغيير). في الكود ، يمكنك إنشاء اسم مستعار متعدد لكائن سلسلة. لكن مراجع هذه الأسماء المستعارة هي نفسها.
على سبيل المثال ، S1 و S2 هما مستعاران للكائنات "droidyue.com" ، ويتم تخزين الاسم المستعار في إشارات إلى الكائن الحقيقي. لذا S1 = S2
السلسلة s1 = "droidyue.com" ؛ السلسلة s2 = s1 ؛ system.out.println ("S1 و S2 لهما نفس المرجع =" + (s1 == s2)) ؛المشغل الوحيد المحمول في جافا
في Java ، يرتبط المشغل الزائد الوحيد بالربط سلسلة. +،+=. إلى جانب ذلك ، لا يسمح مصممو Java بمشغليهم الآخرين.
تحليل الربط
هل هناك حقًا تكلفة أداء؟
بعد فهم النقطتين أعلاه ، قد يكون لديك مثل هذه الأفكار. نظرًا لأن كائن اللدغة غير قابل للتغيير ، فإن الربط بين السلاسل المتعددة (ثلاثة أو أكثر) سوف ينتج حتما كائنات سلسلة وسيطة غير ضرورية.
username username = "Andy" ؛ String Age = "24" ؛ String Job = "Developer" ؛ string info = username + Age + Job ؛
للحصول على المعلومات المذكورة أعلاه ، سيتم تقطيع اسم المستخدم والعمر لإنشاء كائن سلسلة مؤقت T1 ، مع محتوى Andy24 ، ثم سيتم تقطيع T1 والوظائف لإنشاء كائن المعلومات الذي نحتاجه في النهاية. من بينها ، يتم إنشاء T1 وسيطة ، وبعد إنشاء T1 ، لن يتم إعادة تدويره تلقائيًا ، والذي سيشغل حتماً مساحة معينة. إذا كان ذلك عبارة عن ربط الكثير (على افتراض المئات ، أكثر شيوعًا في سلسلة استدعاء tostring للكائن) ، ستكون التكلفة أكبر وستكون الأداء أقل بكثير.
معالجة التحسين المترجم
هل هناك حقًا تكلفة الأداء أعلاه؟ الربط السلسلة شائع جدًا ، ألا يوجد تحسين معالجة خاص؟ الجواب هو أنه يتم إجراء هذا التحسين عندما يقوم المترجم بتجميع .java إلى Bytecode.
إذا أراد برنامج Java تشغيله ، فسوف يستغرق الأمر فترتين ، وقت التجميع ووقت التشغيل. في وقت الترجمة ، يحول برنامج التحويل البرمجي Java (برنامج التحويل البرمجي) ملف Java إلى Bytecode. في وقت التشغيل ، يقوم Java Virtual Machine (JVM) بتشغيل رمز Bytecode الذي تم إنشاؤه. خلال هاتين الفترتين ، حققت Java ما يسمى التجميع والركض في كل مكان.
دعنا نختبر التحسينات التي تم إجراؤها خلال فترة التجميع ، وننشئ جزءًا من التعليمات البرمجية التي قد يكون لها تكاليف أداء.
concatenation {public static void main (string [] args) {String username = "Andy" ؛ العمر العمر = "24" ؛ سلسلة الوظيفة = "المطور" ؛ معلومات السلسلة = اسم المستخدم + العمر + الوظيفة ؛ System.out.println (info) ؛ }}ترجمة concatenation.java. الحصول على concatenation.class
Javac Concatenation.Java
ثم نستخدم javap لإزالة تجميع ملف concatenation.class المترجم. Javap -C التسلس. إذا لم يتم العثور على أمر JAVAP ، فيرجى التفكير في إضافة الدليل حيث يوجد Javap في متغير البيئة أو باستخدام المسار الكامل لـ Javap.
17: 22: 04 -androidyue ~/workspace_adt/strings/src $ javap -c concatenationcompiled من "concatenation.java" concatenation clocatenation {public concatenation () ؛ الكود: 0: aload_0 1: invokespecial #1 // method java/lang/object. الكود: 0: LDC #2 // String Andy 2: Store_1 3: LDC #3 // String 24 5: Store_2 6: LDC #4 // string developer 8: store_3 9: New #5 // class java/lang/stringbuilder 12: dup 13: invokespecial #6 // method java/lang/stringbuilder. 17: invokevirtual #7 // method java/lang/stringbuilder.append: (ljava/lang/string ؛) ljava/lang/stringbuilder ؛ 20: aload_2 21: invokevirtual #7 // method java/lang/stringbuilder.append: (ljava/lang/string ؛) ljava/lang/stringbuilder ؛ 24: aload_3 25: invokevirtual #7 // method java/lang/stringbuilder.append: (ljava/lang/string ؛) ljava/lang/stringbuilder ؛ 28: invokevirtual #8 // الطريقة java/lang/stringbuilder.toString :() ljava/lang/string ؛ 31: المتجر 4 33: getStatic #9 // Field Java/Lang/System.out: ljava/io/printstream ؛ 36: aload 4 38: InvokeVirtual #10 // method java/io/printstream.println: (ljava/lang/string ؛) v 41: return}من بينها ، LDC ، المتجر ، وما إلى ذلك هي تعليمات Java Bytecode ، على غرار تعليمات التجميع. تستخدم التعليقات التالية المحتوى المتعلق بـ Java للتوضيح. يمكننا أن نرى أن هناك العديد من البناء على ذلك ، لكننا نسميها بدون عرض في رمز Java. هذا هو التحسين الذي أدلى به برنامج التحويل البرمجي Java. عندما يواجه برنامج التحويل البرمجي Java الربط سلسلة ، سيقوم بإنشاء كائن StringBuilder. الربط وراءه هو في الواقع استدعاء طريقة إلحاق كائن StringBuilder. وبهذه الطريقة ، لن تكون هناك مشاكل نشعر بالقلق.
التحسين المترجم وحده؟
نظرًا لأن المترجم ساعدنا في التحسين ، هل يكفي الاعتماد فقط على تحسين المترجم؟ بالطبع لا.
دعونا نلقي نظرة على قطعة من الكود لم يتم تحسينها للأداء المنخفض
void public implicitusestringBuilder (string [] القيم) {string result = "" ؛ لـ (int i = 0 ؛ i <border.length ؛ i ++) {result += stable [i] ؛ } system.out.println (نتيجة) ؛}تجميع مع javac وعرض مع javap
11: جديد #5 // class java/lang/stringbuilder 14: dup 15: vokespecial #6 // method java/lang/stringbuilder. java/lang/system.out: ljava/io/printstream ؛ 41: aload_2 42: invokevirtual #10 // method java/io/printstream.println: (ljava/lang/string ؛) v 45: return
من بينها 8: IF_ICMPGE 38 و 35: GOTO 5 تشكل حلقة. 8: IF_ICMPGE 38 تعني أنه إذا كانت المقارنة الصحيح لمكدس معامل JVM أكبر من أو تساوي (النتيجة المعاكسة لـ i <values.length) صحيحة ، فإن القفز إلى السطر 38 (System.out). 35: GOTO 5 يعني القفز مباشرة إلى السطر 5.
ولكن هناك شيء مهم للغاية هنا يحدث إنشاء كائن StringBuilder بين الحلقات ، مما يعني أنه عدد المرات التي ستنشئ فيها الحلقات كائنات stringBuilder ، والتي من الواضح أنها ليست جيدة. رمز عاري منخفض المستوى.
قم بتحسينه قليلاً لتحسين الجودة على الفور.
public void explicitusestringBuilder (string [] القيم) {stringBuilder result = new StringBuilder () ؛ لـ (int i = 0 ؛ i <values.length ؛ i ++) {result.append (القيم [i]) ؛ }}المعلومات المقابلة المترجمة
الفراغ العام explicitusestringBuider (java.lang.string []) ؛ الكود: 0: جديد #5 // class java/lang/stringbuilder 3: dup 4: invokespecial #6 // method java/lang/stringbuilder. 17: aload_1 18: iload_3 19: Aaload 20: InvokeVirtual #7 // method java/lang/stringbuilder.append: (ljava/lang/string ؛) ljava/lang/stringbuilder ؛ 23: POP 24: Iinc 3 ، 1 27: Goto 10 30: Return
كما يتضح من أعلاه ، 13: IF_ICMPGE 30 و 27: تشكل GOTO 10 حلقة حلقة ، بينما 0: New 5 خارج الحلقة ، لذلك لا يتم إنشاء StringBuilder عدة مرات.
بشكل عام ، نحتاج إلى محاولة تجنب إنشاء stringbuilders الضمني أو الصريح في جسم الحلقة. لذلك ، فإن أولئك الذين يفهمون كيفية تجميع الكود وكيفية تنفيذه داخليًا لديهم مستويات عالية نسبيًا من الكود.
إذا كان هناك أي أخطاء في المقالة أعلاه ، فيرجى انتقادها وتصحيحها.
ما سبق هو فرز المعلومات حول ربط سلاسل Java ، وسنستمر في إضافة المعلومات ذات الصلة في المستقبل. شكرا لدعمكم لهذا الموقع!