1
System.out.println ("Hex fun:" + Long.toHexString (0x100000000L + 0xcafebabe));

I have the code above,

In Java, if the operand data type is different,

Do not do widening conversion.

long a = 10;
int b = 2;

a + b -> b is converted to long type.

Over there

Hexadecimal 0xcafebabe -> 32 bit int, because the left operand is of type logn, so it is extended and converted to sign. Incorrect operation value is displayed. Yeah, this is good.

The problem is that if you take a decimal number,

System.out.println (Integer.toHexString (-889275714)); // cafebabe
System.out.println (Long.toHexString (3405691582L)); // cafebabe -> extended

System.out.println (Integer.parseUnsignedInt ("cafebabe", 16)); // 3405691582 (QWORD)

Integer.decode ("0xcafebabe") causes an error.

I have a NumberFormat exception and I do not know why.

System.out.println (Integer.parseUnsignedInt ("cafebabe", 16)); -> This is how I handle it so I can output 32 bit decimal integer with sign.

As far as I know, Java primitives do not reduce the length of the data type depending on the operating system. The test environment worked on 64-bit Windows.

The JDK is version 8.

shmosel
  • 49,289
  • 6
  • 73
  • 138
  • The documentation makes it pretty clear `decode()` basically translates to `parseInt()` with the appropriate base, so I guess the only question is why it was designed that way, which is kind of hard to answer if you're not the designer. – shmosel Nov 08 '18 at 02:03

1 Answers1

0

From the documentation:

This sequence of characters must represent a positive value or a NumberFormatException will be thrown.

You have overflow of integer an a negative number submits to decode method. Because Integer.MAX_VALUE == 2147483647 and 0xcafebabe == 3405691582.

One of the solution for you case is to use Long.decode():

System.out.println ("Hex fun: " + Long.toHexString (0x100000000L + Long.decode ("0xcafebabe")));
// output: Hex fun: 1cafebabe 

Update:
To find out what exactly is going on you need to practice debugging or reading sources:

public static Integer decode(String nm) throws NumberFormatException {
    // some code
    result = Integer.valueOf(nm.substring(index), radix);
    // in our case Integer.valueOf("cafebabe", 16)
    // some code
}

public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return Integer.valueOf(parseInt(s,radix));
}

public static int parseInt(String s, int radix) throws NumberFormatException {
    // some code
    // limit == -Integer.MAX_VALUE == -2147483647
    // multmin == -134217727
    int multmin = limit / radix;
    int result = 0;
    while (i < len) {
        // Accumulating negatively avoids surprises near MAX_VALUE
        int digit = Character.digit(s.charAt(i++), radix);
        if (digit < 0 || result < multmin) {
            throw NumberFormatException.forInputString(s);
        }
        result *= radix;
        if (result < limit + digit) {
            throw NumberFormatException.forInputString(s);
        }
        result -= digit;
    }
    // some code
}

result < multmin prevents integer overflow. On last iteration when i == 7 we will have last digit decoded as digit == 14 and result == -212855723. The result of their multiplication will overflow int. To prevent it we have minimum value before multiplication multmin == limit / radix in our case radix == 16.

uli
  • 671
  • 6
  • 15