JDK-6259307 : Byte.parseByte not working as advertised in the SDK Documentation
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux
  • CPU: x86
  • Submitted: 2005-04-21
  • Updated: 2010-04-02
  • Resolved: 2005-04-21
Description
FULL PRODUCT VERSION :
java version "1.4.2_04"
Java(TM) 2 Runtime Environment. Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.8-24.13-default Suse/Linux

A DESCRIPTION OF THE PROBLEM :

The following line of code throws an NumberFormatException, when according to the documentation on the routine, it should not.

Byte.parseByte("AD",16);



The Documentation states:

public static byte parseByte(String s,  int radix)
                      throws NumberFormatException

Parses the string argument as a signed byte in the radix specified by the second argument. The characters in the string must all be digits, of the specified radix (as determined by whether Character.digit(char, int) returns a nonnegative value) except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value. The resulting byte value is returned ......

Upon investigation, the code in the parseByte routine does the following:

byte parseByte(String s, int radix)
{
      int i = Integer.parseInt(s,radix);
      if(i < MIN_VALUE || i > MAX_VALUE)
         throw new NumberFormatException("Value out of range ......");

      return (byte)i;
}

What should be done to work according to the documentation is the following:

byte parseByte(String s, int radix)
{
     byte b = (byte)Integer.parseInt(s, radix);
     if(b < MIN_VALUE || b > MAX_VALUE)
          throw new NumberFormatException("......");

     return b;
}

This would correct the behavior of the parseByte routine to align with the API documentation.  Leaving the function as is with the documentation as is, is extremely misleading.

AD is a valid hexadecimal byte value, it equates to -83.  If the parseByte routine were invoked in the following manner:

Byte.parseByte("-83");

The code works as advertised and a -83 is placed in the variable expecting the results.

All I can say is both implementations SHOULD work IDENTICALLY regardless of radix and without regard to a '-' sign.  On ALL platforms the most significant bit of a signed byte is the sign bit, and a routine should be able to handle that simple item.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :

execute the two lines of code:

// This works correct
  byte foo = Byte.parseByte("-83");
// The next line is destined to fail
  byte bar = Byte.parseByte("AD",16);

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -

Both lines should work with IDENTICAL results.

-83 should be put in both foo and bar.
ACTUAL -

An NumberFormatException is thrown when the bar value is being assigned.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------


class Foo {

   byte foo;
   byte bar;

   public Foo() {
      this.foo = Byte.parseByte("-83");
      this.bar = Byte.parseByte("AD",16);
   }

   public static main(String args[]) {
      Foo fubar = new Foo();
   }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :

The workaround is simply to replace the line:

this.bar = Byte.parseByte("AD",16);

with

this.bar = (byte)Integer.parseInt("AD",16);

And Wah-Lah (result as expected)
###@###.### 2005-04-21 11:54:47 GMT

Comments
EVALUATION The method in question is behaving exactly as specified. With this method a negative value must be indicated by using a minus sign "-" and not be setting the sign bit by having the high order bit be one. In other words, for base 16 the valid strings range from "-80" (-128) to "7f" (127); "AD" base 16 is positive 173 which is out of range. Closing as not a bug. ###@###.### 2005-04-21 18:26:22 GMT
21-04-2005