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

175

Eu estou querendo saber por que o método String.valueOf(int i)existe? Eu estou usando este método para converter intem Stringe apenas descobriu o Integer.toString(int i)método.

Depois de analisar a implementação desses métodos, vi que o primeiro está chamando o segundo. Como conseqüência, todas as minhas ligações para String.valueOf(int i)envolver mais uma ligação do que diretamenteInteger.toString(int i)

Manuel Selva
fonte
3
Apenas para fins de referência: stackoverflow.com/questions/3335685/integer-tostring
Bobby

Respostas:

46

Apenas duas maneiras diferentes de fazer a mesma coisa. Pode ser um motivo histórico (não me lembro se um veio antes do outro).

mipadi
fonte
22
Sim, mas se algo está fazendo o mesmo, não significa que são a mesma coisa.
Damian Leszczyński - Vash
3
String.valueOf (int) apenas chama Integer.toString (i) diretamente. Então é melhor chamar Integer.toString (int).
djchapm 21/05/19
171

No tipo String, temos vários métodos 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) 

Como podemos ver, esses métodos são capazes de resolver todos os tipos de números

toda implementação de método específico como você apresentou: Então, para números inteiros, temos

Integer.toString(int i)

para dupla

Double.toString(double d)

e assim por diante

Na minha opinião, isso não é algo histórico, mas é mais útil para um desenvolvedor usar o método valueOfda classe String do que do tipo apropriado, pois leva a menos alterações para fazermos.

Amostra 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);

 }

Como vemos na amostra 2, temos que fazer duas alterações, ao contrário da amostra uma.

Na minha conclusão, o uso do valueOfmétodo da classe String é mais flexível e é por isso que está disponível lá.

Damian Leszczyński - Vash
fonte
18
E não se esqueça Integer.toString(int i, int radix)que irá converter para cordas de outros que 10. bases
Stephen P
@Vash Você também pode explicar como usar uma string vazia para converter int em String e comparar com String.valueOf? por exemplo) "" + int i = "i"? Qual é melhor ?
Kanagavelu Sugumar
1
Para formatar int como string, você não deve usar o "" + i. Não existe grande sobrecarga, mas geralmente porque isso não é elegante. Em vez de usar String.valueOf(int), você pode usar String.format("%d",i);para ler mais, visite este site docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash
Eu gostaria que o autoboxing fosse mais inteligente e apenas adicionasse a conversão na compilação ou algo assim.
Rob Grant
1
@RobertGrant A autoboxing não é o caso aqui. Mas, para responder às suas preocupações, é inteligente que você possa fazer isso int i = new Integer("1");e vice-versa.
Damian Leszczyński - Vash
52

Uma grande diferença é que, se você invocar toString()um objeto nulo, obterá um tempo NullPointerException, usando String.valueOf()você pode não verificar se há nulo.

A Costa
fonte
46
A questão é sobre Integer.toString(int i), um staticmétodo. Não há nullobjetos possíveis.
Petr Janeček
14
Integer i = null; i.toString(); // Null pointer exception!! String.valueOf(i); // No exception
manish_s
10
@Manis Kumar: Seu exemplo não irá disparar o String.valueOf(int i)método, mas String.valueOf(Object obj). De qualquer forma, a questão é sobre intvalores primitivos , dos quais não há possibilidade null.
Hleinone 1/11
1
@manish_s ficou bem claro no exemplo que ninguém está falando sobre o tipo de objeto Número inteiro. Estamos falando apenas de primitivos.
Daniel Ochoa
2
@manish_s: O OP não disse Integer.toString()mas Integer.toString(int i). Esse é um método estático ( docs.oracle.com/javase/7/docs/api/java/lang/… ).
LarsH,
13

A classe String fornece métodos valueOf para todos os tipos primitivos e tipo de objeto, portanto, presumo que sejam métodos de conveniência que podem ser acessados ​​por meio de uma classe.

NB Profiling results

Média intToString = 5368ms, Média stringValueOf = 5689ms (para 100.000.000 operações)

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
fonte
7
Seu perfil deve realmente ter um período de "aquecimento", caso contrário, os resultados podem ser distorcidos pelo JIT mexendo nas coisas. Dito isto, uma diferença de 300ms em 10 ^ 8 operações é tão pequena que pode ser completamente desprezível.
Cameron Skinner
1
@Kingo Não acho que seu caso de teste esteja correto. Porque você está atribuindo o valor, String jmas nunca o usa. O compilador subjacente pode ter otimizado isso. É melhor passar o objeto j em um método diferente e fazer alguma operação fictícia.
Rakesh
1
Você realmente não deve escrever micro benchmarks caseiros dessa maneira. Se você usa JMH . Ele cuida do aquecimento, medição do tempo, várias tentativas independentes (bifurca o Java!) E reduz o código (incluindo resultados para diferentes métodos e valores - tempo de execução 7 minutos): gist.github.com/ecki/ 399136f4fd59c1d110c1 (spoiler: "" + n ganho).
Eckes
5
Obrigado amigo, mas minha resposta foi há 5 anos! JMH foi lançado apenas em 2013: P
Kingo
9

Nas fontes 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);
}

Então eles dão exatamente o mesmo resultado e um de fato chama o outro. String.valueOf é mais flexível se você puder alterar o tipo posteriormente.

Davio
fonte
8

Se você olhar para o código-fonte da Stringclasse, ele realmente chamará Integer.toString()quando você ligar valueOf().

Dito isto, Integer.toString()pode ser um pouco mais rápido se as chamadas de método não forem otimizadas em tempo de compilação (o que provavelmente é).

tskuzzy
fonte
Sim e "" + n é ainda mais rápido. Veja gist.github.com/ecki/399136f4fd59c1d110c1
eckes
3

A implementação String.valueOf()que você vê é a maneira mais simples de cumprir o contrato especificado na API: "A representação é exatamente a retornada pelo Integer.toString()método de um argumento".

trashgod
fonte
2

Para responder à pergunta dos OPs, é simplesmente um invólucro auxiliar ter a outra chamada e se resume à escolha do estilo e é isso. Acho que há muita desinformação aqui e a melhor coisa que um desenvolvedor Java pode fazer é analisar a implementação de cada método, a um ou dois cliques de distância em qualquer IDE. Você verá claramente que String.valueOf(int)está simplesmente chamando Integer.toString(int)por você.

Portanto, não há absolutamente nenhuma diferença, pois ambos criam um buffer de caracteres, percorrem os dígitos do número, copiam-o para uma nova String e a retornam (portanto, cada um está criando um objeto String). A única diferença é uma chamada extra, que o compilador elimina para uma única chamada de qualquer maneira.

Portanto, não importa como você chama, além de talvez consistência de código. Quanto aos comentários sobre nulos, é preciso um primitivo, portanto, não pode ser nulo! Você receberá um erro em tempo de compilação se não inicializar o int que está sendo passado. Portanto, não há diferença em como ele lida com nulos, pois eles não existem neste caso.

Steve J
fonte
Você poderia separar seu texto em alguns blocos. É muito difícil de ler.
Magnilex
Há muitas coisas desinformadas neste OP. Sua postagem é a melhor resposta para mim! Obrigado
aksappy 15/09/2015
1

Você não deve se preocupar com esta chamada extra, que lhe custa problemas de eficiência. Se houver algum custo, será mínimo e deve ser insignificante no quadro geral das coisas.

Talvez a razão pela qual ambos existam seja oferecer legibilidade. No contexto de muitos tipos sendo convertidos String, várias chamadas para String.valueOf(SomeType)podem ser mais legíveis do que várias SomeType.toStringchamadas.

poligenelubricants
fonte
1
Na verdade, essas chamadas de uma linha são atendidas rapidamente.
Tassos Bassoukos
Mesmo em um loop chamando 1 000 000 de tempo String.valueof () ??
Manuel Selva
@Manuel: você viu o perfil? Você identificou que aqui reside o seu problema de desempenho? Tem certeza de que não está otimizando prematuramente? @ Tassos: sim, isso também é muito provável, mas de qualquer maneira eu não me preocuparia com isso, a menos que a criação de perfil diga que há um problema com essa chamada em particular.
polygenelubricants
Na verdade, Manuel, eu esperaria que um loop de 1000000 vezes fosse inserido mais frequentemente do que apenas uma ou duas vezes. Mesmo assim, será uma pequena parte do tempo, não importa quantas vezes ele faça um loop.
corsiKa
Não, mas tenho certeza de que não há gargalo aqui no meu aplicativo. Estou apenas perguntando isso, porque não vejo nenhuma preocupação de legibilidade aqui e, portanto, acho que tenho que usar o código mais ideal, mesmo que o ganho seja 0. Você não concorda?
Manuel Selva
1

minha abertura é valueof () sempre chamada tostring () para representação e, portanto, para a representação do tipo primitivo, valueof é generalizada. O objeto .here Integer.toString (int i) cria um limite que converte apenas o número inteiro.

anuragsingh
fonte
1

Não há diferenças entre Integer.toString (5) e String.valueOf (5);

porque String.valueOf retorna:

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

etc ..

Ahamadullah Saikat
fonte
0

Usando o método String.valueOf (), você não precisa se preocupar com os dados (sejam int, long, char, char [], booleano, Object), basta chamar:

  • static String valueOf ()

usar a única sintaxe String.valueOf () pode passar o que você passa como parâmetro é convertido em String e retornado.

Caso contrário, se você usar Integer.toString (), Float.toString () etc. (por exemplo, SomeType.toString ()), será necessário verificar o tipo de dados do parâmetro que deseja converter em string. Portanto, é melhor usar String.valueOf () para essas conversões.

Se você está tendo uma matriz de classe de objeto que contém valores diferentes, como Inteiro, Char, Flutuante etc., usando o método String.valueOf (), você pode converter os elementos dessa matriz em forma de String facilmente. Pelo contrário, se você quiser usar o SomeType.toString (), primeiro você precisará conhecer suas classes de tipo de dados (talvez usando o operador "instanceOf") e, em seguida, somente você poderá prosseguir com uma conversão de tipo.

O método String.valueOf (), quando chamado, corresponde ao parâmetro que é passado (seja Inteiro, Char, Flutuante etc.) e, usando a sobrecarga de método, chama esse método "valueOf ()" cujo parâmetro é correspondido e, dentro desse método, é uma chamada direta para o método "toString ()" correspondente.

Então, podemos ver como a sobrecarga de verificar o tipo de dados e depois chamar o método "toString ()" correspondente é removida. Só precisamos chamar o método String.valueOf (), sem nos importar com o que queremos converter em String.

Conclusão: O método String.valueOf () tem sua importância apenas ao custo de mais uma chamada.

Amit Bhandari
fonte
-3

para sequenciar()

  1. está presente na classe Object, geralmente substituída na classe derivada
  2. typecast para a classe apropriada é necessário chamar o método toString ().

valor de()

  1. Método estático sobrecarregado presente na classe String.
  2. lida com tipos primitivos e com objetos.

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

verifique este link é muito bom. http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

shruti
fonte