Java negativo int all’esagono e ritorno non riesce

public class Main3 { public static void main(String[] args) { Integer min = Integer.MIN_VALUE; String minHex = Integer.toHexString(Integer.MIN_VALUE); System.out.println(min + " " + minHex); System.out.println(Integer.parseInt(minHex, 16)); } } 

 -2147483648 80000000 Exception in thread "main" java.lang.NumberFormatException: For input string: "80000000" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:459) at Main3.main(Main3.java:7) 

Che cosa succede?

È documentato che Integer.toHexString restituisce una rappresentazione di stringa del numero intero come un valore senza segno – mentre Integer.parseInt accetta un int firmato. Se utilizzi Integer.toString(value, 16) , otterrai quello che desideri.

Questo è qualcosa che mi ha sempre infastidito. Se si inizializza un int con un letterale esadecimale, è ansible utilizzare l’intervallo completo di valori positivi fino a 0xFFFFFF ; qualsiasi cosa più grande di 0x7FFFFF sarà davvero un valore negativo. Questo è molto utile per il bit masking e altre operazioni in cui ti interessa solo le posizioni dei bit, non i loro significati.

Ma se usi Integer.parseInt () per convertire una stringa in un intero, qualsiasi cosa più grande di "0x7FFFFFFF" viene considerata come un errore. Probabilmente c’è una buona ragione per cui l’hanno fatto in quel modo, ma è comunque frustrante.

La soluzione più semplice consiste nell’utilizzare Long.parseLong (), quindi convertire il risultato in int.

 int n = (int)Long.parseLong(s, 16); 

Ovviamente, dovresti farlo solo se sei sicuro che il numero sarà nell’intervallo Integer.MIN_VALUE..Integer.MAX_VALUE .

Secondo la documentazione, toHexString restituisce “una rappresentazione in stringa dell’argomento intero come numero intero senza segno nella base 16.”

Quindi l’operazione inversa corretta è probabilmente Integer.parseUnsignedInt che è stato introdotto come parte di Java 8:

 public class Main3 { public static void main(String[] args) { Integer min = Integer.MIN_VALUE; String minHex = Integer.toHexString(Integer.MIN_VALUE); System.out.println(min + " " + minHex); System.out.println(Integer.parseUnsignedInt(minHex, 16)); } 

Prova questo:

 public class Main3 { public static void main(String[] args) { Integer min = Integer.MIN_VALUE; String minHex = Integer.toHexString(Integer.MIN_VALUE); System.out.println(min + " " + minHex); System.out.println(Integer.parseInt( "-" + minHex, 16)); } 

}

per ottenere questo:

 -2147483648 80000000 -2147483648 

Devi includere un segno negativo .

Non ho accesso per testare questo adesso, ma scommetterei se invece tu provassi questo valore:

 Integer min = Integer.MIN_VALUE + 1; 

Non bombarderebbe, ma ti darebbe un numero positivo (non negativo) quando ParseInt(min,16) .

Una stringa di bit in realtà non ha abbastanza informazioni per determinare il segno in questo contesto, quindi è necessario fornirlo. (considera il caso in cui usi min = "F" .) F? + F? Se lo hai convertito in bit e visto 1111, e sapevi che era un byte, potresti concludere che è negativo, ma è un sacco di IFS.

Questo sembra funzionare per me:

 public class Main3 { public static void main(String[] args) { Integer min = Integer.MIN_VALUE; String minHex = Integer.toHexString(Integer.MIN_VALUE); System.out.println(min + " " + minHex); System.out.println((int)Long.parseLong(minHex, 16)); } } 

Il numero intero viene analizzato come “firmato lungo” che gestisce un numero così grande e positivo, quindi il segno viene ritrovato gettandolo su “int”.