Optional وجافا الحديثة

كتل النصوص

15 دقيقة الدرس 7 من 13

كتل النصوص

قبل أن تُصبح كتل النصوص ميزةً نهائية في Java 15، كان تضمين السلاسل متعددة الأسطر أمرًا مؤلمًا. استلزم كتابة أجسام JSON واستعلامات SQL ومقاطع HTML وبيانات XML سلاسل مُدمَجة مع \n يدوية وعلامات اقتباس مُهرَّبة في كل مكان. جاءت كتل النصوص — التي قُدِّمت معاينةً في Java 13 وأُقِرَّت نهائيًا في Java 15 — لحل هذه المشكلة بصياغة واضحة ومقروءة.

الأسلوب القديم مقابل الأسلوب الجديد

إليك نفس سلسلة JSON مكتوبة بالأسلوبين:

// Java 14 وما قبلها — يصعب قراءتها ويسهل الخطأ فيها String json = "{\n" + " \"name\": \"Alice\",\n" + " \"age\": 30,\n" + " \"active\": true\n" + "}"; // Java 15+ — كتلة نص String json = """ { "name": "Alice", "age": 30, "active": true } """;

النسخة الثانية هي ما يبدو عليه ملف المصدر فعلًا — بما فيه المسافات البادئة — دون علامة اقتباس مُهرَّبة واحدة أو تسلسل هروب لسطر جديد.

قواعد الصياغة

تُفتح كتلة النص بثلاث علامات اقتباس مزدوجة (""") يليها مسافات بيضاء اختيارية ثم سطر جديد إلزامي. لا يمكن أن يُتبع """ الفاتح بمحتوى على السطر نفسه. أما """ الختامي فيمكن أن يكون على سطر خاص به (يُضيف سطرًا جديدًا تلاييًا للقيمة) أو يتبع مباشرةً آخر سطر من المحتوى (بدون سطر جديد تلائي).

// يُضاف سطر جديد تلائي — """ الختامي على سطر خاص String withTrailingNewline = """ hello """; // لا يُضاف سطر جديد تلائي — """ الختامي على سطر المحتوى String withoutTrailingNewline = """ hello"""; System.out.println(withTrailingNewline.length()); // 6 (h-e-l-l-o-\n) System.out.println(withoutTrailingNewline.length()); // 5 (h-e-l-l-o)
سطر """ الفاتح لا يُعدّ جزءًا من محتوى السلسلة. وظيفته الوحيدة هي بدء الكتلة وتأسيس خط الأساس للمسافة البادئة. يبدأ المحتوى من السطر التالي مباشرةً.

المسافات البادئة العَرَضية — المفهوم الجوهري

أهم ما يجب فهمه في كتل النصوص هو كيفية تعامل Java مع المسافات البادئة. إن أضفت ثماني مسافات بادئة لكتلة نص لتنسجم مع الكود المحيط، فإن Java لا تُدرج هذه المسافات الثماني في قيمة السلسلة عشوائيًا. بدلًا من ذلك تُزيل المسافات البادئة العَرَضية — أي المسافات البادئة المشتركة بين جميع أسطر المحتوى و""" الختامي.

يعمل """ الختامي كـمرساة للمسافة البادئة. تنظر Java إلى عمود المُحدِّد الختامي وتُزيل ذلك العدد من المسافات البادئة من كل سطر محتوى.

String sql = """ SELECT id, name FROM users WHERE active = 1 """; // """ الختامي في العمود 8 (بدءًا من الصفر). // تُزيل Java 8 مسافات بادئة من كل سطر محتوى. // السلسلة الناتجة: // "SELECT id, name\nFROM users\nWHERE active = 1\n" // — بدون أي مسافات بادئة. System.out.println(sql); // SELECT id, name // FROM users // WHERE active = 1

يمكنك عمدًا الإبقاء على بعض المسافات البادئة بتحريك """ الختامي إلى يسار المحتوى:

String indented = """ line one line two """; // """ الختامي في العمود 8؛ المحتوى في العمود 12 // => تُحفظ 4 مسافات بادئة في كل سطر // " line one\n line two\n"
أفضل الممارسات: اجعل """ الختامي مُحاذيًا لمسافة البداية في كتلة النص نفسها. ينتج عن ذلك صفر مسافات بادئة عَرَضية في المخرجات ويوضّح النية للقارئ فورًا.

تسلسلات الهروب والإضافات الجديدة

تعمل جميع تسلسلات هروب Java المعيارية داخل كتل النصوص: \t و\\ و\uXXXX وغيرها. ولأن علامات الاقتباس المزدوجة لم تعد تحتاج إلى هروب داخل كتلة النص، تحتاج فقط إلى هروب " إذا كانت جزءًا من تسلسل من ثلاث أو أكثر من علامات الاقتباس المتتالية.

قدّمت Java 14 أيضًا تسلسلي هروب جديدين خصيصًا لكتل النصوص:

  • \<محدِّد السطر> — شرطة مائلة عكسية في نهاية سطر المصدر تُلغي السطر الجديد عند تلك النقطة، مما يُتيح تقسيم سطر منطقي طويل عبر عدة أسطر مصدر دون تضمين سطر جديد فعلي في السلسلة.
  • \s — مسافة واحدة لا تُحذف أبدًا بعملية إزالة المسافات العَرَضية. مفيدة لفرض مسافات تلائية في السطر.
// استمرار السطر: القيمة سطر طويل واحد لا ثلاثة أسطر String query = """ SELECT id, name, email \ FROM users \ WHERE active = 1"""; // مكافئ لـ: "SELECT id, name, email FROM users WHERE active = 1" // \s يحفظ مسافة تلائية كانت ستُحذف String aligned = """ RED \s GREEN\s BLUE \s """;

String.formatted() — الاستيفاء بدون مُعامِل جديد

لا تزال Java تفتقر إلى استيفاء سلاسل مُدمَج، لكن كتل النصوص تتناسق بشكل طبيعي مع String.formatted() (أسلوب نسخة أُضيف في Java 15 يستدعي String.format على المُستقبِل):

String template = """ INSERT INTO orders (customer_id, amount, status) VALUES (%d, %.2f, '%s'); """; String sql = template.formatted(42, 199.99, "PENDING"); System.out.println(sql); // INSERT INTO orders (customer_id, amount, status) // VALUES (42, 199.99, 'PENDING');

مثال عملي — تضمين HTML

String html = """ <!DOCTYPE html> <html lang="en"> <head><title>%s</title></head> <body> <h1>%s</h1> </body> </html> """.formatted("Dashboard", "Welcome back!"); System.out.println(html);
كتل النصوص لا تزال كائنات String عادية. إنها ليست نوعًا جديدًا، وليست كسولة التقييم، وليست قوالب. جميع عمليات السلاسل — equals() وsubstring() وreplaceAll() — تعمل بالطريقة نفسها تمامًا. يعالج المُصرِّف المسافات العَرَضية وتسلسلات الهروب في وقت الترجمة؛ أما في وقت التشغيل فكتلة النص مجرد ثابت String اعتيادي.

متى تستخدم كتل النصوص

  • استعلامات SQL الأطول من جملة واحدة — المسافة البادئة تعكس البنية المنطقية.
  • حمولات JSON / XML في الاختبارات أو كود التهيئة.
  • مقاطع HTML أو SVG تُعيدها الدوال المساعدة.
  • سلاسل المخرجات المتوقعة في اختبارات الوحدة — المقارنة بكتلة مقروءة بدلًا من سطر واحد طويل تجعل تشخيص الأخطاء أيسر.
  • قوالب رسائل السجلات ذات العناصر النائبة.

بالنسبة للسلاسل الأحادية السطر البسيطة أو السلاسل المُجمَّعة ديناميكيًا، تظل حرفيات السلاسل العادية وStringBuilder خيارات مثالية تمامًا.

الخلاصة

تتيح لك كتل النصوص كتابة سلاسل متعددة الأسطر بالشكل الذي ينبغي أن تظهر عليه فعلًا، دون تسلسلات هروب أو ضجيج تدمج. الآلية الجوهرية هي إزالة المسافات البادئة العَرَضية التي يتحكم فيها موضع عمود """ الختامي. اجمع كتل النصوص مع .formatted() للمعاملة الخفيفة الوزن، واستخدم استمرار السطر \ لمنع الأسطر الجديدة غير المرغوبة، وتذكر أن الناتج لا يزال String عاديًا تنطبق عليه جميع الواجهات البرمجية الموجودة دون تغيير.