سؤال

تمت إضافة Printf إلى Java مع الإصدار 1.5 ولكن لا يمكنني العثور على كيفية إرسال الإخراج إلى سلسلة بدلاً من ملف (وهو ما يفعله sprintf في C).لا أحد يعرف كيفية القيام بذلك؟

هل كانت مفيدة؟

المحلول

// Store the formatted string in 'result'
String result = String.format("%4d", i * j);

// Write the result to standard output
System.out.println( result );

يرى شكل ولها بناء الجملة

نصائح أخرى

@ إريكسون.

السلاسل هي أنواع غير قابلة للتغيير.لا يمكنك تعديلها، فقط قم بإرجاع مثيلات السلسلة الجديدة.

ولهذا السبب، فإن "foo".format() ليس له أي معنى، حيث يجب أن يُطلق عليه مثل هذا

string newString = "foo".format();

قرر مؤلفو جافا الأصليون (ومؤلفو .NET) أن الطريقة الثابتة أكثر منطقية في هذه الحالة، حيث أنك لا تقوم بتعديل "foo"، ولكن بدلاً من ذلك تستدعي أسلوب تنسيق وتمرير سلسلة إدخال.

يحرر:هيه، هذا الموقع يمكن أن يكون مسليا جدا في بعض الأحيان.لقد حصلت على تصويت سلبي لذكر حقيقة أن السلاسل هي أنواع غير قابلة للتغيير.

فيما يلي مثال على سبب كون Format() غبيًا كطريقة مثيل.في .NET (وربما في Java)، تعد Replace() طريقة مثيل.

انت تستطيع فعل ذالك:

 "I Like Wine".Replace("Wine","Beer");

ومع ذلك، لا يحدث شيء، لأن السلاسل غير قابلة للتغيير.يحاول Replace إرجاع سلسلة جديدة، لكن لم يتم تعيينها لأي شيء.

وهذا يسبب الكثير من الأخطاء الشائعة للمبتدئين مثل:

// Contrived Example
inputText.Replace(" ","%20");

مرة أخرى، لا يحدث شيء، بدلاً من ذلك عليك القيام بما يلي:

inputText = inputText.Replace(" ","%20");

الآن، إذا فهمت أن الأوتار غير قابلة للتغيير، فهذا منطقي تمامًا.إذا لم تقم بذلك، فأنت في حيرة من أمرك.المكان المناسب للاستبدال، سيكون حيث يوجد التنسيق، كطريقة ثابتة للسلسلة:

 inputText = String.Replace(inputText," ", "%20");

الآن ليس هناك شك حول ما يحدث.

السؤال الحقيقي هو، لماذا قرر مؤلفو هذه الأطر أن يكون أحدهما طريقة مثيل والآخر ثابتًا؟في رأيي، يتم التعبير عن كليهما بشكل أكثر أناقة كطرق ثابتة، ولكن يبدو أن إريكسون يعتقد أن كلاهما ينتميان إلى طرق مثيل.

بغض النظر عن رأيك، فالحقيقة هي أنك أقل عرضة لارتكاب الأخطاء باستخدام الإصدار الثابت، كما أن الكود أسهل في الفهم (No Hidden Gotchas).

بالطبع هناك بعض الأساليب المثالية كطرق مثيل، خذ String.Length()

int length = "123".Length();

في هذه الحالة، من الواضح أننا لا نحاول تعديل "123"، بل نقوم فقط بفحصه وإعادة طوله...هذا مرشح مثالي لطريقة المثيل.

قواعدي البسيطة لطرق المثيل على الكائنات غير القابلة للتغيير:

  • إذا كنت بحاجة إلى إرجاع مثيل جديد من نفس النوع، فاستخدم طريقة ثابتة.
  • بخلاف ذلك، استخدم طريقة المثيل.

يعمل كلا الحلين على محاكاة printf، ولكن بطريقة مختلفة.على سبيل المثال، لتحويل قيمة إلى سلسلة سداسية عشرية، لديك الحلين التاليين:

  • مع format(), ، الأقرب إلى sprintf():

    final static String HexChars = "0123456789abcdef";
    
    public static String getHexQuad(long v) {
        String ret;
        if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = "";
        ret += String.format("%c%c%c%c",
            HexChars.charAt((int) ((v >> 12) & 0x0f)),
            HexChars.charAt((int) ((v >>  8) & 0x0f)),
            HexChars.charAt((int) ((v >>  4) & 0x0f)),
            HexChars.charAt((int) ( v        & 0x0f)));
        return ret;
    }
    
  • مع replace(char oldchar , char newchar), أسرع إلى حد ما ولكنه محدود جدًا:

        ...
        ret += "ABCD".
            replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))).
            replace('B', HexChars.charAt((int) ((v >>  8) & 0x0f))).
            replace('C', HexChars.charAt((int) ((v >>  4) & 0x0f))).
            replace('D', HexChars.charAt((int) ( v        & 0x0f)));
        ...
    
  • هناك حل ثالث يتكون من مجرد إضافة الحرف إلى ret واحدًا تلو الآخر (char عبارة عن أرقام إضافة إلى بعضها البعض!) مثلما في:

    ...
    ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
    ret += HexChars.charAt((int) ((v >>  8) & 0x0f)));
    ...
    

...ولكن هذا سيكون حقًا قبيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top