(String) o .toString ()?


89

Ho un metodo con un Object oparametro.

In questo metodo, so esattamente che c'è una String"o" che non è nulla. Non è necessario controllare o fare qualcos'altro. Devo trattarlo esattamente come un Stringoggetto.

Solo curioso - cosa è più economico - lanciarlo Stringo usarlo Object.toString()? O è lo stesso per tempo- / cpu- / mem- prezzo?

Aggiornamento: il metodo accetta Objectperché è l'implementazione di un'interfaccia. Non è possibile modificare il tipo di parametro.

E non può essere nullaffatto. Volevo solo dire che non ho bisogno di controllarlo per null o vuoto. Nel mio caso, c'è sempre una stringa non vuota.


1
Nel mondo .NET, l'abbiamo misurato e ToString () è più veloce. Dato il motivo per cui è così, lo stesso è quasi certamente vero per una JVM jitting.
Joshua

Risposte:


72

il casting su una stringa è più economico poiché non richiede una chiamata di funzione esterna, ma solo il controllo del tipo interno.


4
Lo hai testato su più JRE? Ho visto risultati sorprendenti proprio per questa situazione in .NET. Realisticamente dubito che le prestazioni siano importanti nella vita reale, ma il casting è migliore dal punto di vista del codice difensivo.
Jon Skeet

La chiamata al metodo dovrebbe essere inline. Usare i generici per rimuovere il cast (esplicito) sarebbe il migliore.
Tom Hawtin - tackline

@ Jon Skeet: Sono d'accordo che la differenza di prestazioni non sarà molto. @ Tom Hawtin: Poiché il tipo di oggetto che verrà ricevuto non è noto in fase di compilazione, non riesco a vedere come la chiamata al metodo possa essere inline. Puoi per favore chiarire?
euphoria83

@ euphoria83: Integrato dal compilatore JIT, non da javac.
Michael Myers

In realtà no, il metodo non può essere integrato. Il tipo è noto solo per essere Object e l'implementazione effettiva dipende dal tipo di runtime. Quale sia più veloce dipende ancora dall'implementazione, ma per quanto ricordo (in realtà l'ho testato con microbenchmark a un certo punto), il casting sembra essere più veloce. Questa non è una risposta ovvia: il controllo del tipo non è sempre più veloce. Per il tipo String può essere poiché è un oggetto (non un'interfaccia) e finale.
StaxMan

45

Userei un cast. Ciò convalida la tua "conoscenza" che è una stringa. Se per qualsiasi motivo ti ritrovi con un bug e qualcuno passa qualcosa di diverso da una stringa, penso che sarebbe meglio lanciare un'eccezione (cosa che farà un cast) piuttosto che continuare a eseguire con dati difettosi.



7

Se sai che Object o è una stringa, direi di lanciarlo su una stringa e applicarlo in questo modo. Chiamare toString () su un oggetto che conosci per certo è una stringa potrebbe semplicemente aggiungere confusione.

Se Object o potrebbe essere qualcosa di diverso da una String, dovrai chiamare toString ().


Questa è la risposta corretta per me. Perché? Perché il casting (string)Registry.GetValue...genera un'eccezione per il tentativo di eseguire il cast di un oggetto Int32, mentre Registry.GetValue...ToString()funziona come previsto.
gravità

3

Non sarei troppo preoccupato per le prestazioni, se questa operazione fosse eseguita anche solo poche migliaia di volte al secondo, non c'è differenza tangibile.

Tuttavia, mi preoccuperei di "conoscere" l'input. Hai un metodo che accetta un Objecte dovresti trattarlo come tale, cioè non dovresti sapere nulla del parametro, a parte il fatto che aderisce Objectall'interfaccia, che ha untoString() metodo. In questo caso, suggerirei caldamente di utilizzare quel metodo invece di assumere qualsiasi cosa.

OTOH, se l'ingresso è sempre uno Stringo null, semplicemente modificare il metodo di accettare Strings, e controllare in modo esplicito per la nulls (che si dovrebbe fare comunque ogni volta che fare con i non-primitive ...)


Ho detto che la mia domanda non ha alcun significato di valore :) Sono solo curioso di sapere cosa è teoricamente più economico. Ma grazie comunque
Vugluskr

Il costo dipenderà dall'efficienza della VM nelle chiamate ai metodi virtuali rispetto al controllo del tipo. Questo è specifico dell'implementazione.
Jon Skeet

2

Dato che il tipo di riferimento è un Object e tutti gli oggetti hanno toString (), basta chiamare object.toString (). String.toString () restituisce solo questo.

  • toString () è meno codice da digitare.
  • toString () è meno bytecode.
  • il casting è un'operazione costosa VS una chiamata polimorfica.
  • il cast potrebbe fallire.
  • Usa String.valueOf (object) che chiama solo object.toString () se non è nullo.

1

Se quello che hai in "o" è una stringa, non c'è molta differenza (probabilmente il cast è più veloce, ma questa è una cosa di implementazione VM / libreria).

Se "o" potrebbe non essere una stringa ma dovrebbe essere una stringa, il cast è ciò che desideri (ma dovresti fare in modo che il metodo prenda una stringa invece di un oggetto).

Se "o" può essere di qualsiasi tipo, devi usare toString, ma assicurati di controllare prima la presenza di null.

void foo(final Object o)
{
    final String str;

    // without this you would get a class cast exception
    // be wary of using instanceof though - it is usually the wrong thing to do
    if(o instanceof String)
    {
        str = (String)o;
    }    
}

o

void foo(final Object o)
{
    final String str;

    // if you are 100% sure that o is not null then you can get rid of the else
    if(o != null)
    {
        str = o.toString();
    }
}

Preferisco codificare l'ultimo come:

void foo(final Object o)
{
    final String str;

    if(o == null)
    {
        throw new IllegalArgumentException("o cannot be null");
    }

    str = o.toString();
}

I primi 2 frammenti non verranno realmente compilati (la finalvariabile potrebbe non essere stata inizializzata). Hai bisogno di un elseche genererà un'eccezione o inizializzerà strqualcosa.
Bruno Reis

1

Ho scoperto stranamente che il cast era più lento della ricerca vtable implicita nella chiamata tostring.


1

Non può esserci una "stringa nulla in o". Se o è nullo, non contiene una stringa nulla, è solo nullo. Prima controlla o per null. Se esegui il cast o chiami ToString () su null, andrai in crash.


2
Il casting di null non andrà in crash. Non genererà nemmeno una NullPointerException, chiamerà semplicemente null al nuovo tipo. :)
Bombe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.