Domanda

Come faccio a moltiplicare 10 per an Integer oggetto e recuperare il Integer oggetto?

Sto cercando il modo più accurato per farlo.

Probabilmente lo farei in questo modo:Ottieni informazioni da Integer object, moltiplicalo con l'altro int e crea un altro oggetto Integer con questo valore int.

Il codice sarà qualcosa di simile...

integerObj = new Integer(integerObj.intValue() * 10);

Ma ho visto un codice in cui l'autore lo fa in questo modo:Ottenere il String dal Integer oggetto, concatenare "0" alla fine e poi ottenere Integer oggetto indietro utilizzando Integer.parseInt

Il codice è qualcosa del genere:

String s = integerObj + "0";
integerObj = Integer.parseInt(s);

C'è qualche merito nel farlo in ogni caso?

E quale sarebbe il modo più efficiente/più accurato in generale e in questo caso?

È stato utile?

Soluzione

Con Java 5 autoboxing, puoi semplicemente fare:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);

Altri suggerimenti

L'approccio con le stringhe è divertente, ma quasi certamente è un pessimo modo per farlo.

Ottenere il valore int di un numero intero e crearne uno nuovo sarà molto veloce, mentre as parseInt sarebbe piuttosto costoso da chiamare.

Nel complesso, sono d'accordo con il tuo approccio originale (che, come altri hanno sottolineato, può essere fatto senza tanta confusione se hai l'autoboxing introdotto in Java 5).

Il problema con il secondo modo è il modo in cui le stringhe vengono gestite in Java:

  • "0" viene convertito in un oggetto String costante in fase di compilazione.
  • Ogni volta che viene chiamato questo codice, s viene costruito come un nuovo oggetto String e javac converte quel codice in String s = new StringBuilder().append(integerObj.toString()).append("0").toString() (StringBuffer per le versioni precedenti).Anche se usi lo stesso integerObj, cioè.,

    String s1 = integerObj + "0"; String s2 = integerObj + "0";

    (s1 == s2) sarebbe false, Mentre s1.equals(s2) sarebbe true.

  • Integer.parseInt chiamate interne new Integer() comunque, perché Integer è immutabile.

A proposito, l'autoboxing/unboxing è internamente uguale al primo metodo.

Stai lontano dal secondo approccio, la soluzione migliore sarebbe l'autoboxing se stai utilizzando Java 1.5, qualsiasi cosa prima del tuo primo esempio sarebbe la migliore.

La soluzione che utilizza il metodo String non è altrettanto buona per una serie di motivi.Alcuni sono motivi estetici, altri sono pratici.

Sul fronte pratico vengono creati più oggetti dalla versione String rispetto alla forma più normale (come hai espresso nel tuo primo esempio).

Dal punto di vista estetico, penso che la seconda versione oscuri l'intento del codice e questo è importante quasi quanto far sì che produca il risultato desiderato.

La risposta del toolkit sopra è corretta ed è il modo migliore, ma non fornisce una spiegazione completa di ciò che sta accadendo.Supponendo Java 5 o successivo:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20

Quello che devi sapere è che è esattamente la stessa cosa che fare:

Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20

Eseguendo l'operazione (in questo caso *=) sull'oggetto 'a', non si modifica il valore int all'interno dell'oggetto 'a', ma si assegna effettivamente un nuovo oggetto ad 'a'.Questo perché "a" viene decompresso automaticamente per eseguire la moltiplicazione, quindi il risultato della moltiplicazione viene decompresso automaticamente e assegnato ad "a".

Il numero intero è un oggetto immutabile.(Tutte le classi wrapper sono immutabili.)

Prendiamo ad esempio questo pezzo di codice:

static void test() {
    Integer i = new Integer(10);
    System.out.println("StartingMemory: " + System.identityHashCode(i));
    changeInteger(i);
    System.out.println("Step1: " + i);
    changeInteger(++i);
    System.out.println("Step2: " + i.intValue());
    System.out.println("MiddleMemory: " + System.identityHashCode(i));
}

static void changeInteger(Integer i) {
    System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
    System.out.println("ChangeStartValue: " + i);
    i++;
    System.out.println("ChangeEnd: " + i);
    System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}

L'output sarà:

StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520

Puoi vedere che l'indirizzo di memoria per 'i' sta cambiando (i tuoi indirizzi di memoria saranno diversi).

Ora facciamo un piccolo test con riflessione, aggiungiamolo alla fine del metodo test():

System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
    final Field f = i.getClass().getDeclaredField("value");
    f.setAccessible(true);
    f.setInt(i, 15);
    System.out.println("Step3: " + i.intValue());
    System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
    e.printStackTrace();
}

L'output aggiuntivo sarà:

MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520

Puoi vedere che l'indirizzo di memoria per "i" non è cambiato, anche se ne abbiamo modificato il valore utilizzando la riflessione.
(NON USARE LA RIFLESSIONE IN QUESTO MODO NELLA VITA REALE!!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top