Integer.toString (int i) vs String.valueOf (int i)


176

Мені цікаво, чому метод String.valueOf(int i)існує? Я використовую цей метод для перетворення intна метод, який Stringщойно відкрив Integer.toString(int i).

Переглянувши реалізацію цих методів, я побачив, що перший називає другий. Як наслідок, усі мої дзвінки String.valueOf(int i)залучати ще один дзвінок, ніж безпосередньо дзвінокInteger.toString(int i)


3
Тільки для довідки: stackoverflow.com/questions/3335685/integer-tostring
Боббі

Відповіді:


46

Просто два різні способи зробити те саме. Це може бути історичною причиною (не пам'ятаю, чи прийшов один до іншого).


22
Так, але якщо щось робить те саме, це не означає, що це те саме.
Damian Leszczyński - Vash

3
String.valueOf (int) просто викликає Integer.toString (i) безпосередньо. Тож краще зателефонувати на Integer.toString (int).
djchapm

171

У типу String у нас є кілька методів valueOf

static String   valueOf(boolean b) 
static String   valueOf(char c) 
static String   valueOf(char[] data) 
static String   valueOf(char[] data, int offset, int count) 
static String   valueOf(double d) 
static String   valueOf(float f) 
static String   valueOf(int i) 
static String   valueOf(long l) 
static String   valueOf(Object obj) 

Як ми бачимо, цей метод здатний вирішувати всі види чисел

кожна реалізація конкретного методу, як ви представили: Отже, для цілих чисел у нас є

Integer.toString(int i)

для подвійних

Double.toString(double d)

і так далі

На мою думку, це не є якоюсь історичною річчю, але розробникові корисніше використовувати метод valueOfіз класу String, ніж належного типу, оскільки це призводить до менших змін для нас.

Зразок 1:

public String doStuff(int num) {

  // Do something with num...

  return String.valueOf(num);

 }

Зразок2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Як ми бачимо у зразку 2, ми повинні зробити дві зміни, на відміну від вибірки.

На мій висновок, використання valueOfметоду з класу String є більш гнучким, і тому він доступний там.


18
І не забувайте, Integer.toString(int i, int radix)що перетворитесь на рядки баз, окрім 10.
Stephen P

@Vash Чи не могли б ви пояснити, як використовувати порожню рядок для перетворення int в String порівняти зі String.valueOf? наприклад) "" + int i = "i"? Що найкраще?
Канагавелу Сугумар

1
Щоб форматувати int як рядок, ви не повинні використовувати "" + i. Не існує великого над головою, але взагалі тому, що це не елегантно. Замість використання String.valueOf(int)ви можете String.format("%d",i);прочитати більше, будь ласка, відвідайте цей веб-сайт docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash

Я хотів би, щоб автобоксинг був розумнішим і просто додав перетворення на компіляцію чи щось таке.
Роб Грант

1
@RobertGrant Автобоксінгу тут не так. Але відповісти на ваші побоювання, це розумно, оскільки ви можете це зробити int i = new Integer("1");і навпаки.
Даміян Лещинський - Ваш

52

Одна величезна відмінність полягає в тому, що якщо ви toString()почнете викликати нульовий об'єкт, ви отримаєте " NullPointerExceptionтой час", використовуючи його, String.valueOf()ви можете не перевірити на "null".


46
Питання про Integer.toString(int i), staticметод. Там немає nullоб'єктів можливо.
Петро Янечек

14
Integer i = null; i.toString(); // Null pointer exception!! String.valueOf(i); // No exception
manish_s

10
@Manis Kumar: Ваш приклад не запустить String.valueOf(int i)метод, але String.valueOf(Object obj). У всякому разі, питання стосується примітивних intзначень, де немає можливості null.
хлейнон

1
@manish_s з прикладу було досить зрозуміло, що ніхто не говорить про тип об'єкта Integer. Ми говоримо лише про примітиви.
Даніель Очоа

2
@manish_s: ОП не сказав, Integer.toString()але Integer.toString(int i). Це статичний метод ( docs.oracle.com/javase/7/docs/api/java/lang/… ).
LarsH

13

Клас String забезпечує методи valueOf для всіх примітивних типів та типу Object, тому я припускаю, що це зручні методи, до яких можна отримати доступ через один клас.

NB Результати профілювання

Середнє значення intToString = 5368 мс, середнє рядокValueOf = 5689 мс (для 100 000 000 операцій)

public class StringIntTest {


    public static long intToString () {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = Integer.toString(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static long stringValueOf () {

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = String.valueOf(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static void main(String[] args) {
        long intToStringElapsed = 0;
        long stringValueOfElapsed = 0;
        for (int i = 0; i < 10; i++) {
            intToStringElapsed += intToString();
            stringValueOfElapsed+= stringValueOf();
        }
        System.out.println("Average intToString = "+ (intToStringElapsed /10));
        System.out.println("Average stringValueOf = " +(stringValueOfElapsed / 10));
    }
}

7
У вашому профілюванні дійсно повинен бути період «розминки», інакше результати можуть бути перекошені JIT-майстерністю з речами. Однак, різниця в 300 мс за 10 ^ 8 операцій настільки мала, що є абсолютно незначною.
Камерон Скіннер

1
@Kingo Я не думаю, що ваш тестовий випадок є правильним. Тому що ви присвоюєте цінність, String jале ніколи не використовуєте. Основний компілятор, можливо, оптимізував це. Краще передати j-об’єкт іншим методом і зробити кілька операцій з манекеном.
Ракеш

1
Ви дійсно не повинні писати таким чином домашні мікро-орієнтири. Якщо ви використовуєте JMH . Він піклується про розминку, вимірювання часу, кілька незалежних спроб (вилки Java!) І робить код невеликим, він виглядає так (включаючи результати для різних методів і значень - час виконання 7 хвилин): gist.github.com/ecki/ 399136f4fd59c1d110c1 (спойлер: "" + n виграв).
eckes

5
Дякую приятелю, але моя відповідь була 5 років тому! JMH був випущений лише у 2013 році: P
Kingo

9

З джерел Java:

/**
 * Returns the string representation of the {@code int} argument.
 * <p>
 * The representation is exactly the one returned by the
 * {@code Integer.toString} method of one argument.
 *
 * @param   i   an {@code int}.
 * @return  a string representation of the {@code int} argument.
 * @see     java.lang.Integer#toString(int, int)
 */
public static String valueOf(int i) {
    return Integer.toString(i);
}

Тож вони дають абсолютно однаковий результат і один насправді називає інший. String.valueOf є більш гнучким, якщо ви можете пізніше змінити тип.


8

Якщо ви подивитеся на вихідний код Stringкласу, він насправді дзвонить, Integer.toString()коли ви дзвоните valueOf().

Це, Integer.toString()можливо, буде швидше, якщо виклики методу не будуть оптимізовані під час компіляції (що вони, мабуть, є).


Так і "" + n ще швидше. Дивіться gist.github.com/ecki/399136f4fd59c1d110c1
eckes

3

Реалізація того, String.valueOf()що ви бачите, є найпростішим способом виконання контракту, визначеного в API: "Представлення - це саме те, що повертається Integer.toString()методом одного аргументу".


2

Щоб відповісти на питання ОП, просто інший дзвінок-помічник має інший виклик і зводиться до вибору стилю, і це все. Я думаю, що тут багато дезінформації, і найкраще, що може зробити розробник Java, - це дивитись на реалізацію кожного методу, це один або два кліки в будь-якому IDE. Ви чітко побачите, що String.valueOf(int)це просто закликає Integer.toString(int)вас.

Тому існує абсолютно нульова різниця в тому, що вони обидва створюють буфер символів, проходять через цифри числа, потім копіюють його в новий рядок і повертають його (тому кожен створює один об'єкт String). Різниця - це лише один додатковий виклик, який компілятор у будь-якому випадку усуває до одного виклику.

Тож важливо не те, що ви називаєте, крім можливо узгодженості коду. Що стосується коментарів про нулі, то вона потрібна примітиву, тому вона не може бути нульовою! Ви отримаєте помилку часу компіляції, якщо не будете ініціалізувати переданий int. Тож немає різниці в тому, як він обробляє нулі, оскільки їх у цьому випадку немає.


Чи можете ви поділіть текст на кілька блоків. Це дуже важко читати.
Magnilex

У цій ОП є багато дезінформованих речей. Ваш пост - найкраща відповідь для мене! Дякую
aksappy

1

Ви не повинні турбуватися з приводу цього додаткового дзвінка, який коштуватиме вам проблем з ефективністю. Якщо є якісь кошти, вони будуть мінімальними, і вони повинні бути незначними у більшій картині речей.

Можливо, причиною існування обох є пропонування читабельності. У контексті багатьох типів, до яких перетворюються String, різні дзвінки String.valueOf(SomeType)можуть бути читабельнішими, ніж різні SomeType.toStringдзвінки.


1
Насправді такі однолінійні дзвінки вбудовуються досить швидко.
Тассос Басукос

Навіть у циклі, що викликає 1 000 000 часу String.valueof () ??
Мануель Сельва

@Manuel: ти це профі? Ви визначили, що в цьому криється ваша проблема ефективності? Ви впевнені, що не передчасно оптимізуєте? @Tassos: так, це також дуже ймовірно, але в будь-якому випадку я б не хвилювався з цього приводу, якщо профілювання не скаже, що з цим викликом є ​​проблема.
полігенмастильні матеріали

Насправді, Мануель, я б очікував, що цикл, що збирається 1000000 разів, стане вводитись частіше, ніж просто переходити раз або два. Незважаючи на це, це пройде невелику частину часу, незалежно від того, скільки разів це циклічно.
corsiKa

Ні, але я впевнений, що в моєму додатку немає горловини для пляшок. Я просто запитую це, тому що я не бачу тут ніякого занепокоєння щодо читабельності, і тому я думаю, що мені доведеться використовувати більш оптимальний код, навіть якщо посилення дорівнює 0. Чи не згодні ви?
Мануель Сельва

1

моє відкриття valueof () завжди викликається tostring () для представлення і так для rpresentaion примітивного типу valueof узагальнюється. а java за замовчуванням не підтримує тип даних, але він визначає його роботу з objaect і класифікує все, що робиться в класах і робиться object .here Integer.toString (int i) створити обмеження, яке перетворює лише ціле число.


1

Немає відмінностей між Integer.toString (5) та String.valueOf (5);

тому що String.valueOf повертає:

public static String valueOf(int i) {
    return Integer.toString(i);
}
public static String valueOf(float f) {
    return Float.toString(f);
}

тощо.


0

Використовуючи метод String.valueOf (), вам не доведеться турбуватися про дані (будь то int, long, char, char [], boolean, Object), ви можете просто зателефонувати:

  • static String valueOf ()

за допомогою єдиного синтаксису String.valueOf () можна все, що ви передаєте в якості параметра, перетворюється в String і повертається ..

В іншому випадку, якщо ви використовуєте Integer.toString (), Float.toString () тощо (тобто SomeType.toString ()), вам доведеться перевірити тип даних параметра, який ви хочете перетворити в рядок. Отже, для таких перетворень краще використовувати String.valueOf ().

Якщо у вас є масив об’єктного класу, який містить різні значення, такі як Integer, Char, Float і т.д., то, використовуючи метод String.valueOf (), ви можете легко перетворити елементи такого масиву в String форму. Навпаки, якщо ви хочете використовувати SomeType.toString (), то спочатку вам потрібно буде знати про їхні типи типів даних (можливо, використовуючи оператор "instanceOf"), і тільки тоді ви можете перейти до набору тексту.

Метод String.valueOf (), коли викликається, відповідає параметру, який передається (будь-якому його Integer, Char, Float тощо) та використовуючи метод перевантаження, викликає метод "valueOf ()", параметр якого відповідає, а потім всередині цього методу є їх прямий виклик відповідного методу "toString ()".

Отже, ми можемо бачити, як видаляється накладні перевірки типу даних, а потім викликає відповідний метод "toString ()". Тільки нам потрібно викликати метод String.valueOf (), не піклуючись про те, що ми хочемо перетворити на String.

Висновок: метод String.valueOf () має своє значення лише за рахунок ще одного виклику.


-3

toString ()

  1. присутній у класі Object, як правило, переосмислений у похідному класі
  2. для виклику до відповідного класу необхідно викликати метод toString ().

valueOf ()

  1. Перевантажений статичний метод, присутній у класі String.
  2. обробляє примітивні типи, а також типи об'єктів.

    Integer a = null;
    System.out.println(Integer.toString()) ; NUll pointer exception
    System.out.println(String.valueOf() ; give NULL as value

перевірити це посилання дуже добре. http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.