Printf був доданий до Java з версією 1.5, але я не можу знайти, як відправити вихід у рядок, а не у файл (що і спринт робить у C). Хтось знає, як це зробити?
Printf був доданий до Java з версією 1.5, але я не можу знайти, як відправити вихід у рядок, а не у файл (що і спринт робить у C). Хтось знає, як це зробити?
Відповіді:
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
Струни - це непорушні типи. Ви не можете їх змінювати, повертати лише нові екземпляри рядків.
Через це форматування методом екземпляра мало сенсу, так як його потрібно було б назвати так:
String formatted = "%s: %s".format(key, value);
Оригінальні автори Java (та автори .NET) вирішили, що статичний метод має більше сенсу в цій ситуації, оскільки ви не змінюєте ціль, а натомість викликаєте метод форматування та передаєте у рядок введення.
Ось приклад того, чому format()
був би німий як метод екземпляра. У .NET (і, мабуть, у Java), Replace()
це метод екземпляра.
Ви можете зробити це:
"I Like Wine".Replace("Wine","Beer");
Однак нічого не відбувається, бо рядки незмінні. Replace()
намагається повернути новий рядок, але він призначається ні до чого.
Це викликає безліч поширених помилок новичка, таких як:
inputText.Replace(" ", "%20");
Знову ж нічого не відбувається, натомість ви повинні зробити:
inputText = inputText.Replace(" ","%20");
Тепер, якщо ви розумієте, що рядки незмінні, це має ідеальний сенс. Якщо ви цього не зробите, то ви просто розгублені. Правильним місцем для розташування Replace()
буде format()
як статичний метод String
:
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)));
...
... але це було б справді некрасиво.
Ви можете зробити printf до всього, що є OutputStream за допомогою PrintStream. Так чи інакше, друкуючи в потоковий рядок:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
baos.reset(); //need reset to write new string
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
System.out.println(baos.toString());
baos.reset();
Потоковий рядок може бути створений таким чином ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();