Integer.toString (int i) против 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

Просто два разных способа сделать одно и то же. Это может быть историческая причина (не могу вспомнить, если один пришел раньше другого).

mipadi
источник
22
Да, но если что-то делает то же самое, не значит, что это одно и то же.
Дамиан Лещинский - Ваш
3
String.valueOf (int) просто вызывает Integer.toString (i) напрямую. Так что лучше всего позвонить Integer.toString (int).
djchapm
171

В строковом типе у нас есть несколько методов 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);

 }

Sample2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Как мы видим в примере 2, мы должны сделать два изменения, в отличие от образца один.

В моем заключении, использование valueOfметода из класса String является более гибким, и поэтому он доступен там.

Дамиан Лещинский - Ваш
источник
18
И не забывайте, Integer.toString(int i, int radix)что будет преобразовывать в строки оснований, отличных от 10.
Стивен 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 Лещинского - Vash
Я хотел бы, чтобы автобокс был умнее и просто добавил преобразование при компиляции или что-то в этом роде.
Роб Грант
1
@RobertGrant Автобокс здесь не тот случай. Но чтобы ответить на ваши вопросы, это разумно, как вы можете сделать это, int i = new Integer("1");и наоборот.
Дамиан Лещинский - Ваш
52

Одно огромное отличие состоит в том, что если вы вызываете toString()в нулевом объекте, вы получите какое- NullPointerExceptionто время, используя, String.valueOf()вы можете не проверять нулевое значение.

Коста
источник
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.
Hleinone
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 для всех примитивных типов и типов объектов, поэтому я предполагаю, что это удобные методы, к которым можно получить доступ через один класс.

NB Профилирование результатов

Среднее значение intToString = 5368 мс, среднее значение stringValueOf = 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));
    }
}
Kingo
источник
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()может быть немного быстрее, если вызовы методов не оптимизированы во время компиляции (что они, вероятно, и есть).

tskuzzy
источник
Да и "" + n еще быстрее. См. Gist.github.com/ecki/399136f4fd59c1d110c1
eckes
3

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

trashgod
источник
2

Чтобы ответить на вопрос OPs, это просто вспомогательная оболочка для второго вызова, и все сводится к выбору стиля, и это все. Я думаю, что здесь много дезинформации, и лучшее, что может сделать разработчик Java, - это посмотреть на реализацию каждого метода, он находится на расстоянии одного или двух кликов в любой IDE. Вы четко увидите, что String.valueOf(int)просто зовет Integer.toString(int)вас.

Следовательно, разница абсолютно нулевая: они оба создают буфер символов, просматривают цифры в числе, затем копируют это в новую строку и возвращают ее (поэтому каждый из них создает один объект строки). Разница лишь в одном дополнительном вызове, который компилятор исключает в любом случае.

Поэтому важно не то, что вы называете, кроме, возможно, согласованности кода. Что касается комментариев о нулях, то он принимает примитив, поэтому он не может быть нулевым! Вы получите ошибку во время компиляции, если не инициализируете передаваемый int. Таким образом, нет никакой разницы в том, как он обрабатывает пустые значения, так как в этом случае они отсутствуют.

Стив Дж
источник
Не могли бы вы разделить ваш текст на несколько блоков. Это очень трудно читать.
Magnilex
В этом ОП много дезинформированных вещей. Ваш пост - лучший ответ для меня! Спасибо
aksappy
1

Вам не стоит беспокоиться об этом дополнительном звонке, который стоит вам проблем с эффективностью. Если есть какая-либо стоимость, она будет минимальной и должна быть незначительной в общей картине вещей.

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

polygenelubricants
источник
1
На самом деле, такие однострочные вызовы довольно быстро вводятся.
Тассос Бассукос
Даже в цикле вызова 1 000 000 раз String.valueof () ??
Мануэль Сельва
@Manuel: ты профилировал это? Вы определили, что в этом заключается ваша проблема производительности? Вы уверены, что не преждевременно оптимизируете? @Tassos: да, это также очень вероятно, но в любом случае я бы не стал беспокоиться об этом, если бы в профилировании не было проблемы с этим конкретным вызовом.
полигенасмазочные материалы
На самом деле, Мануэль, я ожидал бы, что цикл, проходящий 1000000 раз, будет вставлен чаще, чем просто один или два раза. Тем не менее, это будет небольшая часть времени, независимо от того, сколько раз это повторяется.
CorsiKa
Нет, но я уверен, что в моем приложении нет бутылочного горлышка. Я просто спрашиваю об этом, потому что я не вижу здесь никаких проблем с читабельностью, и поэтому я думаю, что должен использовать более оптимальный код, даже если коэффициент усиления равен 0. Вы согласны?
Мануэль Сельва
1

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

anuragsingh
источник
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

нанизывать()

  1. присутствует в классе Object, обычно переопределяется в производном классе
  2. Чтобы вызвать соответствующий класс, необходимо вызвать метод toString ().

значение()

  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/

шрути
источник