-
s = new String("xyz"); كم عدد كائنات السلسلة التي تم إنشاؤها؟ كائنان، أحدهما "xyx" والآخر هو الكائن المرجعي الذي يشير إلى "xyx".
String s="Hello";int i=3; هل هذا التعبير صحيح في جافا، سيطالبك بأن نوع البيانات غير متطابق. لأن السلسلة هي فئة! النهج الصحيح: s+="3" أو s+='3' أو s+=(char)i;
سنقدم طريقة أخرى لإنشاء كائنات السلسلة - النص المحاط بعلامات اقتباس. هذه الطريقة فريدة بالنسبة للسلسلة، وهي مختلفة تمامًا عن الطريقة الجديدة.
يوجد تجمع سلسلة في جهاز JAVA الظاهري (JVM)، والذي يخزن العديد من كائنات السلسلة ويمكن مشاركته، لذلك فهو يحسن الكفاءة. String a = "abc"؛، عند تنفيذ هذا السطر من التعليمات البرمجية، يبحث جهاز JAVA الظاهري أولاً في تجمع السلسلة لمعرفة ما إذا كان هذا الكائن ذو القيمة "abc" موجودًا بالفعل. أساس الحكم هو فئة السلسلة يساوي (Object obj) القيمة المرجعة للطريقة. إذا كان هناك، فلن يتم إنشاء كائن جديد، وسيتم إرجاع مرجع إلى الكائن الموجود مباشرة؛ وإذا لم يكن الأمر كذلك، فسيتم إنشاء الكائن أولاً، ثم إضافته إلى تجمع السلسلة، ثم سيتم إرجاع مرجعه.
إنشاء كائنات سلسلة: نظرًا للاستخدام المكثف لكائنات السلسلة [إنها كائن، بشكل عام، تقوم الكائنات دائمًا بتخصيص الذاكرة في الكومة]، في Java، من أجل توفير مساحة الذاكرة ووقت التشغيل [مثل عند مقارنة السلاسل، == أفضل من يساوي ()]، يتم وضع جميع القيم الحرفية للسلسلة في تجمع حرفي أثناء مرحلة الترجمة، ويصبح التجمع الحرفي لوقت التشغيل جزءًا من التجمع الثابت. تتمثل ميزة التجمع الحرفي في أنه يتم دمج جميع ثوابت السلسلة نفسها في التجمع وتشغل مساحة واحدة فقط. نحن نعلم أنه بالنسبة لمتغيرين مرجعيين، استخدم == لتحديد ما إذا كانت قيمهما [المراجع] متساوية، أي أنهما يشيران إلى نفس الكائن:
انظر الآن إلى عبارة String s = new String("abc"); هنا، "abc" نفسه عبارة عن كائن في التجمع، وعندما يتم تنفيذ String() الجديدة في وقت التشغيل، يتم وضع نسخة من الكائن في التجمع. في الكومة، وقم بتسليم مرجع هذا الكائن في الكومة إلى s. حسنًا، هذا البيان ينشئ كائنين من السلسلة.
String s1 = new String("abc") ;String s2 = new String("abc") ;if( s1 == s2 ){ // البيان الذي لن يتم تنفيذه}
// كم عدد كائنات السلسلة التي تم إنشاؤها؟ [ثلاثة، واحد في التجمع واثنان في الكومة. ]
ستتم إضافة الكائنات الجديدة التي تم إنشاؤها بواسطة اتصال "+" بين كائنات السلسلة التي تم إنشاؤها باستخدام علامات الاقتباس لتضمين النص فقط إلى تجمع السلاسل. بالنسبة لجميع تعبيرات الاتصال "+" التي تحتوي على كائنات جديدة تم إنشاؤها في الطريقة الجديدة (بما في ذلك القيمة الخالية)، لن تتم إضافة الكائنات الجديدة التي تنشئها إلى تجمع السلاسل.
1.== يعني أنه تمت الإشارة إليها من نفس الكائن، ويعني يساوي () أن القيم متساوية.
String str1 = "abc"؛ الكائن المشار إليه موجود في المكدس (أو تجمع السلسلة).
String str1 =new String ("abc")؛ الكائن المشار إليه موجود في الذاكرة/الكومة.
2.String str1 = "سلسلة"؛
String str3 = "str";
String str4 = "ing";
String str2 = str3+str4; في الكومة، لأن وظيفة العلامة + هي إرجاع كائن سلسلة آخر تم إنشاؤه حديثًا بدلاً من البحث عن قيمة السلسلة في المكدس. إذا كانت String str2 = "str"+"ing"؛ فستكون النتيجة النهائية على المكدس. str1==str2 صحيح.
ولكن هناك حالة واحدة تتطلب اهتمامنا. يرجى إلقاء نظرة على الكود أدناه:
الطبقة العامة StringStaticTest {
السلسلة النهائية العامة الثابتة A = "ab"؛
السلسلة النهائية العامة الثابتة B = "cd"؛
public static void main(String[] args) {
String s = A + B; // تهيئة s عن طريق ربط الثوابتين بـ +
سلسلة t = "abcd";
إذا (ق == ر) {
System.out.println("s يساوي t، هما نفس الكائن");
} آخر {
System.out.println("s لا تساوي t، فهي ليست نفس الكائن");
}
}
}
نتيجة تشغيل هذا الكود هي كما يلي:
s يساوي t، وهما نفس الكائن
والسبب هو أنه في المثال أعلاه، A وB ثابتان وقيمتهما ثابتة، لذا فإن قيمة s ثابتة أيضًا، ويتم تحديدها عند تجميع الفصل. وهذا يعني: String s=A+B يعادل: String s="ab"+"cd";
اسمحوا لي أن أغير المثال أعلاه قليلاً وأرى ما سيحدث:
الطبقة العامة StringStaticTest {
السلسلة النهائية العامة الثابتة أ؛
السلسلة النهائية العامة الثابتة B؛
ثابت {
أ = "أب"؛
ب = "قرص مضغوط";
}
public static void main(String[] args) {
// تهيئة s من خلال ربط الثوابتين بـ +
سلسلة ق = أ + ب؛
سلسلة t = "abcd";
إذا (ق == ر) {
System.out.println("s يساوي t، هما نفس الكائن");
} آخر {
System.out.println("s لا تساوي t، فهي ليست نفس الكائن");
}
}
}
نتيجة عملها هي كما يلي:
s لا يساوي t، فهما ليسا نفس الكائن
لقد أجريت للتو تغييرًا بسيطًا، وكانت النتيجة عكس المثال تمامًا الآن. دعونا نحللها مرة أخرى. على الرغم من تعريف A وB كثوابت (لا يمكن تعيينهما إلا مرة واحدة)، إلا أنه لا يتم تعيينهما على الفور. قبل أن يتم حساب قيمة s، متى يتم تخصيصها والقيمة المخصصة لها كلها متغيرات. لذلك، يتصرف A وB كمتغير قبل تعيين قيمة له. ثم لا يمكن تحديد s في وقت الترجمة، ولكن يمكن إنشاؤها فقط في وقت التشغيل.
أخيرًا، دعونا نتحدث عن تخزين كائنات السلسلة في جهاز JAVA الظاهري (JVM)، والعلاقة بين تجمع السلسلة والكومة والمكدس. دعونا أولاً نراجع الفرق بين الكومة والمكدس:
المكدس: يحفظ بشكل أساسي الأنواع الأساسية (أو الأنواع المضمنة) (char، byte، short، int، long، float، double، boolean) ويمكن مشاركة بيانات الكائنات، وتأتي سرعتها في المرتبة الثانية بعد التسجيل كومة.
الكومة: تستخدم لتخزين الأشياء.
عندما ننظر إلى الكود المصدري لفئة السلسلة، سنجد أنه يحتوي على سمة قيمة، والتي تخزن قيمة كائن السلسلة، والنوع هو char[]، والذي يوضح أيضًا أن السلسلة عبارة عن سلسلة من الأحرف. عند تنفيذ String a = "abc"؛، يقوم جهاز JAVA الظاهري بإنشاء ثلاث قيم أحرف "a" و"b" و"c" في المكدس، ثم يقوم بإنشاء كائن سلسلة في الكومة، قيمته (القيمة) عبارة عن مصفوفة من ثلاث قيم أحرف تم إنشاؤها للتو على المكدس {'a'، 'b'، 'c'}. وأخيرًا، سيتم إضافة كائن السلسلة الذي تم إنشاؤه حديثًا إلى تجمع السلاسل.
إذا قمنا بعد ذلك بتنفيذ الكود String b=new String("abc"); منذ إنشاء "abc" وحفظه في تجمع السلاسل، فسيقوم جهاز JAVA الظاهري بإنشاء كائن سلسلة جديد فقط في الكومة، ولكنه القيمة هي قيم أنواع الأحرف الثلاثة "a" و"b" و"c" التي تم إنشاؤها على المكدس عند تنفيذ السطر السابق من التعليمات البرمجية.
في هذه المرحلة، أصبحنا واضحين تمامًا بشأن السؤال عن سبب قيام String str=new String("abc") المرفوعة في بداية هذه المقالة بإنشاء كائنين.
هذه المقالة مأخوذة من مدونة CSDN، يرجى الإشارة إلى المصدر عند إعادة الطباعة: http://blog.csdn.net/yakihappy/archive/2009/03/10/3977169.aspx.
هذه المقالة مأخوذة من مدونة CSDN، يرجى الإشارة إلى المصدر عند إعادة الطباعة: http://blog.csdn.net/Foxalien/archive/2009/12/18/5029470.aspx.
-