/** * Instances of class <code>Short</code> represent primitive <code>short</code> values. * * <p>Additionally, this class provides various helper functions and variables related to shorts. * * @author Paul Fisher * @author John Keiser * @author Eric Blake ([email protected]) * @since 1.1 * @status updated to 1.4 */ public final class Short extends Number implements Comparable { /** Compatible with JDK 1.1+. */ private static final long serialVersionUID = 7515723908773894738L; /** The minimum value a <code>short</code> can represent is -32768 (or -2<sup>15</sup>). */ public static final short MIN_VALUE = -32768; /** The minimum value a <code>short</code> can represent is 32767 (or 2<sup>15</sup>). */ public static final short MAX_VALUE = 32767; /** The primitive type <code>short</code> is represented by this <code>Class</code> object. */ public static final Class TYPE = VMClassLoader.getPrimitiveClass('S'); /** * The immutable value of this Short. * * @serial the wrapped short */ private final short value; /** * Create a <code>Short</code> object representing the value of the <code>short</code> argument. * * @param value the value to use */ public Short(short value) { this.value = value; } /** * Create a <code>Short</code> object representing the value of the argument after conversion to a * <code>short</code>. * * @param s the string to convert * @throws NumberFormatException if the String cannot be parsed */ public Short(String s) { value = parseShort(s, 10); } /** * Converts the <code>short</code> to a <code>String</code> and assumes a radix of 10. * * @param s the <code>short</code> to convert to <code>String</code> * @return the <code>String</code> representation of the argument */ public static String toString(short s) { return String.valueOf(s); } /** * Converts the specified <code>String</code> into a <code>short</code>. This function assumes a * radix of 10. * * @param s the <code>String</code> to convert * @return the <code>short</code> value of <code>s</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>short</code> */ public static short parseShort(String s) { return parseShort(s, 10); } /** * Converts the specified <code>String</code> into a <code>short</code> using the specified radix * (base). The string must not be <code>null</code> or empty. It may begin with an optional '-', * which will negate the answer, provided that there are also valid digits. Each digit is parsed * as if by <code>Character.digit(d, radix)</code>, and must be in the range <code>0</code> to * <code>radix - 1</code>. Finally, the result must be within <code>MIN_VALUE</code> to <code> * MAX_VALUE</code>, inclusive. Unlike Double.parseDouble, you may not have a leading '+'. * * @param s the <code>String</code> to convert * @param radix the radix (base) to use in the conversion * @return the <code>String</code> argument converted to <code>short</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>short</code> */ public static short parseShort(String s, int radix) { int i = Integer.parseInt(s, radix, false); if ((short) i != i) throw new NumberFormatException(); return (short) i; } /** * Creates a new <code>Short</code> object using the <code>String</code> and specified radix * (base). * * @param s the <code>String</code> to convert * @param radix the radix (base) to convert with * @return the new <code>Short</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>short</code> * @see #parseShort(String, int) */ public static Short valueOf(String s, int radix) { return new Short(parseShort(s, radix)); } /** * Creates a new <code>Short</code> object using the <code>String</code>, assuming a radix of 10. * * @param s the <code>String</code> to convert * @return the new <code>Short</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>short</code> * @see #Short(String) * @see #parseShort(String) */ public static Short valueOf(String s) { return new Short(parseShort(s, 10)); } /** * Convert the specified <code>String</code> into a <code>Short</code>. The <code>String</code> * may represent decimal, hexadecimal, or octal numbers. * * <p>The extended BNF grammar is as follows:<br> * * <pre> * <em>DecodableString</em>: * ( [ <code>-</code> ] <em>DecimalNumber</em> ) * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } ) * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) * <em>DecimalNumber</em>: * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } * <em>DecimalDigit</em>: * <em>Character.digit(d, 10) has value 0 to 9</em> * <em>OctalDigit</em>: * <em>Character.digit(d, 8) has value 0 to 7</em> * <em>DecimalDigit</em>: * <em>Character.digit(d, 16) has value 0 to 15</em> * </pre> * * Finally, the value must be in the range <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, or an * exception is thrown. * * @param s the <code>String</code> to interpret * @return the value of the String as a <code>Short</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>short</code> * @throws NullPointerException if <code>s</code> is null * @see Integer#decode(String) */ public static Short decode(String s) { int i = Integer.parseInt(s, 10, true); if ((short) i != i) throw new NumberFormatException(); return new Short((short) i); } /** * Return the value of this <code>Short</code> as a <code>byte</code>. * * @return the byte value */ public byte byteValue() { return (byte) value; } /** * Return the value of this <code>Short</code>. * * @return the short value */ public short shortValue() { return value; } /** * Return the value of this <code>Short</code> as an <code>int</code>. * * @return the int value */ public int intValue() { return value; } /** * Return the value of this <code>Short</code> as a <code>long</code>. * * @return the long value */ public long longValue() { return value; } /** * Return the value of this <code>Short</code> as a <code>float</code>. * * @return the float value */ public float floatValue() { return value; } /** * Return the value of this <code>Short</code> as a <code>double</code>. * * @return the double value */ public double doubleValue() { return value; } /** * Converts the <code>Short</code> value to a <code>String</code> and assumes a radix of 10. * * @return the <code>String</code> representation of this <code>Short</code> */ public String toString() { return String.valueOf(value); } /** * Return a hashcode representing this Object. <code>Short</code>'s hash code is simply its value. * * @return this Object's hash code */ public int hashCode() { return value; } /** * Returns <code>true</code> if <code>obj</code> is an instance of <code>Short</code> and * represents the same short value. * * @param obj the object to compare * @return whether these Objects are semantically equal */ public boolean equals(Object obj) { return obj instanceof Short && value == ((Short) obj).value; } /** * Compare two Shorts numerically by comparing their <code>short</code> values. The result is * positive if the first is greater, negative if the second is greater, and 0 if the two are * equal. * * @param s the Short to compare * @return the comparison * @since 1.2 */ public int compareTo(Short s) { return value - s.value; } /** * Behaves like <code>compareTo(Short)</code> unless the Object is not a <code>Short</code>. * * @param o the object to compare * @return the comparison * @throws ClassCastException if the argument is not a <code>Short</code> * @see #compareTo(Short) * @see Comparable * @since 1.2 */ public int compareTo(Object o) { return compareTo((Short) o); } }
/** * Instances of class <code>Integer</code> represent primitive <code>int</code> values. * * <p>Additionally, this class provides various helper functions and variables related to ints. * * @author Paul Fisher * @author John Keiser * @author Warren Levy * @author Eric Blake ([email protected]) * @author Tom Tromey ([email protected]) * @author Andrew John Hughes ([email protected]) * @author Ian Rogers * @since 1.0 * @status updated to 1.5 */ public final class Integer extends Number implements Comparable<Integer> { /** Compatible with JDK 1.0.2+. */ private static final long serialVersionUID = 1360826667806852920L; /** The minimum value an <code>int</code> can represent is -2147483648 (or -2<sup>31</sup>). */ public static final int MIN_VALUE = 0x80000000; /** The maximum value an <code>int</code> can represent is 2147483647 (or 2<sup>31</sup> - 1). */ public static final int MAX_VALUE = 0x7fffffff; /** * The primitive type <code>int</code> is represented by this <code>Class</code> object. * * @since 1.1 */ public static final Class<Integer> TYPE = (Class<Integer>) VMClassLoader.getPrimitiveClass('I'); /** * The number of bits needed to represent an <code>int</code>. * * @since 1.5 */ public static final int SIZE = 32; // This caches some Integer values, and is used by boxing // conversions via valueOf(). We must cache at least -128..127; // these constants control how much we actually cache. private static final int MIN_CACHE = -128; private static final int MAX_CACHE = 127; private static final Integer[] intCache = new Integer[MAX_CACHE - MIN_CACHE + 1]; static { for (int i = MIN_CACHE; i <= MAX_CACHE; i++) intCache[i - MIN_CACHE] = new Integer(i); } /** * The immutable value of this Integer. * * @serial the wrapped int */ private final int value; /** * Create an <code>Integer</code> object representing the value of the <code>int</code> argument. * * @param value the value to use */ public Integer(int value) { this.value = value; } /** * Create an <code>Integer</code> object representing the value of the argument after conversion * to an <code>int</code>. * * @param s the string to convert * @throws NumberFormatException if the String does not contain an int * @see #valueOf(String) */ public Integer(String s) { value = parseInt(s, 10, false); } /** * Return the size of a string large enough to hold the given number * * @param num the number we want the string length for (must be positive) * @param radix the radix (base) that will be used for the string * @return a size sufficient for a string of num */ private static int stringSize(int num, int radix) { int exp; if (radix < 4) { exp = 1; } else if (radix < 8) { exp = 2; } else if (radix < 16) { exp = 3; } else if (radix < 32) { exp = 4; } else { exp = 5; } int size = 0; do { num >>>= exp; size++; } while (num != 0); return size; } /** * Converts the <code>int</code> to a <code>String</code> using the specified radix (base). If the * radix exceeds <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10 is used * instead. If the result is negative, the leading character is '-' ('\\u002D'). The remaining * characters come from <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z'). * * @param num the <code>int</code> to convert to <code>String</code> * @param radix the radix (base) to use in the conversion * @return the <code>String</code> representation of the argument */ public static String toString(int num, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; // Is the value negative? boolean isNeg = num < 0; // Is the string a single character? if (!isNeg && num < radix) return new String(digits, num, 1, true); // Compute string size and allocate buffer // account for a leading '-' if the value is negative int size; int i; char[] buffer; if (isNeg) { num = -num; // When the value is MIN_VALUE, it overflows when made positive if (num < 0) { i = size = stringSize(MAX_VALUE, radix) + 2; buffer = new char[size]; buffer[--i] = digits[(int) (-(num + radix) % radix)]; num = -(num / radix); } else { i = size = stringSize(num, radix) + 1; buffer = new char[size]; } } else { i = size = stringSize(num, radix); buffer = new char[size]; } do { buffer[--i] = digits[num % radix]; num /= radix; } while (num > 0); if (isNeg) buffer[--i] = '-'; // Package constructor avoids an array copy. return new String(buffer, i, size - i, true); } /** * Converts the <code>int</code> to a <code>String</code> assuming it is unsigned in base 16. * * @param i the <code>int</code> to convert to <code>String</code> * @return the <code>String</code> representation of the argument */ public static String toHexString(int i) { return toUnsignedString(i, 4); } /** * Converts the <code>int</code> to a <code>String</code> assuming it is unsigned in base 8. * * @param i the <code>int</code> to convert to <code>String</code> * @return the <code>String</code> representation of the argument */ public static String toOctalString(int i) { return toUnsignedString(i, 3); } /** * Converts the <code>int</code> to a <code>String</code> assuming it is unsigned in base 2. * * @param i the <code>int</code> to convert to <code>String</code> * @return the <code>String</code> representation of the argument */ public static String toBinaryString(int i) { return toUnsignedString(i, 1); } /** * Converts the <code>int</code> to a <code>String</code> and assumes a radix of 10. * * @param i the <code>int</code> to convert to <code>String</code> * @return the <code>String</code> representation of the argument * @see #toString(int, int) */ public static String toString(int i) { // This is tricky: in libgcj, String.valueOf(int) is a fast native // implementation. In Classpath it just calls back to // Integer.toString(int, int). return String.valueOf(i); } /** * Converts the specified <code>String</code> into an <code>int</code> using the specified radix * (base). The string must not be <code>null</code> or empty. It may begin with an optional '-', * which will negate the answer, provided that there are also valid digits. Each digit is parsed * as if by <code>Character.digit(d, radix)</code>, and must be in the range <code>0</code> to * <code>radix - 1</code>. Finally, the result must be within <code>MIN_VALUE</code> to <code> * MAX_VALUE</code>, inclusive. Unlike Double.parseDouble, you may not have a leading '+'. * * @param str the <code>String</code> to convert * @param radix the radix (base) to use in the conversion * @return the <code>String</code> argument converted to <code>int</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as an <code>int</code> */ public static int parseInt(String str, int radix) { return parseInt(str, radix, false); } /** * Converts the specified <code>String</code> into an <code>int</code>. This function assumes a * radix of 10. * * @param s the <code>String</code> to convert * @return the <code>int</code> value of <code>s</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as an <code>int</code> * @see #parseInt(String, int) */ public static int parseInt(String s) { return parseInt(s, 10, false); } /** * Creates a new <code>Integer</code> object using the <code>String</code> and specified radix * (base). * * @param s the <code>String</code> to convert * @param radix the radix (base) to convert with * @return the new <code>Integer</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as an <code>int</code> * @see #parseInt(String, int) */ public static Integer valueOf(String s, int radix) { return valueOf(parseInt(s, radix, false)); } /** * Creates a new <code>Integer</code> object using the <code>String</code>, assuming a radix of * 10. * * @param s the <code>String</code> to convert * @return the new <code>Integer</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as an <code>int</code> * @see #Integer(String) * @see #parseInt(String) */ public static Integer valueOf(String s) { return valueOf(parseInt(s, 10, false)); } /** * Returns an <code>Integer</code> object wrapping the value. In contrast to the <code>Integer * </code> constructor, this method will cache some values. It is used by boxing conversion. * * @param val the value to wrap * @return the <code>Integer</code> */ public static Integer valueOf(int val) { if (val < MIN_CACHE || val > MAX_CACHE) return new Integer(val); else return intCache[val - MIN_CACHE]; } /** * Return the value of this <code>Integer</code> as a <code>byte</code>. * * @return the byte value */ public byte byteValue() { return (byte) value; } /** * Return the value of this <code>Integer</code> as a <code>short</code>. * * @return the short value */ public short shortValue() { return (short) value; } /** * Return the value of this <code>Integer</code>. * * @return the int value */ public int intValue() { return value; } /** * Return the value of this <code>Integer</code> as a <code>long</code>. * * @return the long value */ public long longValue() { return value; } /** * Return the value of this <code>Integer</code> as a <code>float</code>. * * @return the float value */ public float floatValue() { return value; } /** * Return the value of this <code>Integer</code> as a <code>double</code>. * * @return the double value */ public double doubleValue() { return value; } /** * Converts the <code>Integer</code> value to a <code>String</code> and assumes a radix of 10. * * @return the <code>String</code> representation */ public String toString() { return String.valueOf(value); } /** * Return a hashcode representing this Object. <code>Integer</code>'s hash code is simply its * value. * * @return this Object's hash code */ public int hashCode() { return value; } /** * Returns <code>true</code> if <code>obj</code> is an instance of <code>Integer</code> and * represents the same int value. * * @param obj the object to compare * @return whether these Objects are semantically equal */ public boolean equals(Object obj) { return obj instanceof Integer && value == ((Integer) obj).value; } /** * Get the specified system property as an <code>Integer</code>. The <code>decode()</code> method * will be used to interpret the value of the property. * * @param nm the name of the system property * @return the system property as an <code>Integer</code>, or null if the property is not found or * cannot be decoded * @throws SecurityException if accessing the system property is forbidden * @see System#getProperty(String) * @see #decode(String) */ public static Integer getInteger(String nm) { return getInteger(nm, null); } /** * Get the specified system property as an <code>Integer</code>, or use a default <code>int</code> * value if the property is not found or is not decodable. The <code>decode()</code> method will * be used to interpret the value of the property. * * @param nm the name of the system property * @param val the default value * @return the value of the system property, or the default * @throws SecurityException if accessing the system property is forbidden * @see System#getProperty(String) * @see #decode(String) */ public static Integer getInteger(String nm, int val) { Integer result = getInteger(nm, null); return result == null ? valueOf(val) : result; } /** * Get the specified system property as an <code>Integer</code>, or use a default <code>Integer * </code> value if the property is not found or is not decodable. The <code>decode()</code> * method will be used to interpret the value of the property. * * @param nm the name of the system property * @param def the default value * @return the value of the system property, or the default * @throws SecurityException if accessing the system property is forbidden * @see System#getProperty(String) * @see #decode(String) */ public static Integer getInteger(String nm, Integer def) { if (nm == null || "".equals(nm)) return def; nm = System.getProperty(nm); if (nm == null) return def; try { return decode(nm); } catch (NumberFormatException e) { return def; } } /** * Convert the specified <code>String</code> into an <code>Integer</code>. The <code>String</code> * may represent decimal, hexadecimal, or octal numbers. * * <p>The extended BNF grammar is as follows:<br> * * <pre> * <em>DecodableString</em>: * ( [ <code>-</code> ] <em>DecimalNumber</em> ) * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } ) * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) * <em>DecimalNumber</em>: * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } * <em>DecimalDigit</em>: * <em>Character.digit(d, 10) has value 0 to 9</em> * <em>OctalDigit</em>: * <em>Character.digit(d, 8) has value 0 to 7</em> * <em>DecimalDigit</em>: * <em>Character.digit(d, 16) has value 0 to 15</em> * </pre> * * Finally, the value must be in the range <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, or an * exception is thrown. * * @param str the <code>String</code> to interpret * @return the value of the String as an <code>Integer</code> * @throws NumberFormatException if <code>s</code> cannot be parsed as a <code>int</code> * @throws NullPointerException if <code>s</code> is null * @since 1.2 */ public static Integer decode(String str) { return valueOf(parseInt(str, 10, true)); } /** * Compare two Integers numerically by comparing their <code>int</code> values. The result is * positive if the first is greater, negative if the second is greater, and 0 if the two are * equal. * * @param i the Integer to compare * @return the comparison * @since 1.2 */ public int compareTo(Integer i) { if (value == i.value) return 0; // Returns just -1 or 1 on inequality; doing math might overflow. return value > i.value ? 1 : -1; } /** * Return the number of bits set in x. * * @param x value to examine * @since 1.5 */ public static int bitCount(int x) { // Successively collapse alternating bit groups into a sum. x = ((x >> 1) & 0x55555555) + (x & 0x55555555); x = ((x >> 2) & 0x33333333) + (x & 0x33333333); x = ((x >> 4) & 0x0f0f0f0f) + (x & 0x0f0f0f0f); x = ((x >> 8) & 0x00ff00ff) + (x & 0x00ff00ff); return ((x >> 16) & 0x0000ffff) + (x & 0x0000ffff); } /** * Rotate x to the left by distance bits. * * @param x the value to rotate * @param distance the number of bits by which to rotate * @since 1.5 */ public static int rotateLeft(int x, int distance) { // This trick works because the shift operators implicitly mask // the shift count. return (x << distance) | (x >>> -distance); } /** * Rotate x to the right by distance bits. * * @param x the value to rotate * @param distance the number of bits by which to rotate * @since 1.5 */ public static int rotateRight(int x, int distance) { // This trick works because the shift operators implicitly mask // the shift count. return (x << -distance) | (x >>> distance); } /** * Find the highest set bit in value, and return a new value with only that bit set. * * @param value the value to examine * @since 1.5 */ public static int highestOneBit(int value) { value |= value >>> 1; value |= value >>> 2; value |= value >>> 4; value |= value >>> 8; value |= value >>> 16; return value ^ (value >>> 1); } /** * Return the number of leading zeros in value. * * @param value the value to examine * @since 1.5 */ public static int numberOfLeadingZeros(int value) { value |= value >>> 1; value |= value >>> 2; value |= value >>> 4; value |= value >>> 8; value |= value >>> 16; return bitCount(~value); } /** * Find the lowest set bit in value, and return a new value with only that bit set. * * @param value the value to examine * @since 1.5 */ public static int lowestOneBit(int value) { // Classic assembly trick. return value & -value; } /** * Find the number of trailing zeros in value. * * @param value the value to examine * @since 1.5 */ public static int numberOfTrailingZeros(int value) { return bitCount((value & -value) - 1); } /** * Return 1 if x is positive, -1 if it is negative, and 0 if it is zero. * * @param x the value to examine * @since 1.5 */ public static int signum(int x) { return (x >> 31) | (-x >>> 31); // The LHS propagates the sign bit through every bit in the word; // if X < 0, every bit is set to 1, else 0. if X > 0, the RHS // negates x and shifts the resulting 1 in the sign bit to the // LSB, leaving every other bit 0. // Hacker's Delight, Section 2-7 } /** * Reverse the bytes in val. * * @since 1.5 */ public static int reverseBytes(int val) { return (((val >> 24) & 0xff) | ((val >> 8) & 0xff00) | ((val << 8) & 0xff0000) | ((val << 24) & 0xff000000)); } /** * Reverse the bits in val. * * @since 1.5 */ public static int reverse(int val) { // Successively swap alternating bit groups. val = ((val >> 1) & 0x55555555) + ((val << 1) & ~0x55555555); val = ((val >> 2) & 0x33333333) + ((val << 2) & ~0x33333333); val = ((val >> 4) & 0x0f0f0f0f) + ((val << 4) & ~0x0f0f0f0f); val = ((val >> 8) & 0x00ff00ff) + ((val << 8) & ~0x00ff00ff); return ((val >> 16) & 0x0000ffff) + ((val << 16) & ~0x0000ffff); } /** * Helper for converting unsigned numbers to String. * * @param num the number * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex) */ // Package visible for use by Long. static String toUnsignedString(int num, int exp) { // Compute string length int size = 1; int copy = num >>> exp; while (copy != 0) { size++; copy >>>= exp; } // Quick path for single character strings if (size == 1) return new String(digits, num, 1, true); // Encode into buffer int mask = (1 << exp) - 1; char[] buffer = new char[size]; int i = size; do { buffer[--i] = digits[num & mask]; num >>>= exp; } while (num != 0); // Package constructor avoids an array copy. return new String(buffer, i, size - i, true); } /** * Helper for parsing ints, used by Integer, Short, and Byte. * * @param str the string to parse * @param radix the radix to use, must be 10 if decode is true * @param decode if called from decode * @return the parsed int value * @throws NumberFormatException if there is an error * @throws NullPointerException if decode is true and str if null * @see #parseInt(String, int) * @see #decode(String) * @see Byte#parseByte(String, int) * @see Short#parseShort(String, int) */ static int parseInt(String str, int radix, boolean decode) { if (!decode && str == null) throw new NumberFormatException(); int index = 0; int len = str.length(); boolean isNeg = false; if (len == 0) throw new NumberFormatException("string length is null"); int ch = str.charAt(index); if (ch == '-') { if (len == 1) throw new NumberFormatException("pure '-'"); isNeg = true; ch = str.charAt(++index); } else if (ch == '+') { if (len == 1) throw new NumberFormatException("pure '+'"); ch = str.charAt(++index); } if (decode) { if (ch == '0') { if (++index == len) return 0; if ((str.charAt(index) & ~('x' ^ 'X')) == 'X') { radix = 16; index++; } else radix = 8; } else if (ch == '#') { radix = 16; index++; } } if (index == len) throw new NumberFormatException("non terminated number: " + str); int max = MAX_VALUE / radix; // We can't directly write `max = (MAX_VALUE + 1) / radix'. // So instead we fake it. if (isNeg && MAX_VALUE % radix == radix - 1) ++max; int val = 0; while (index < len) { if (val < 0 || val > max) throw new NumberFormatException("number overflow (pos=" + index + ") : " + str); ch = Character.digit(str.charAt(index++), radix); val = val * radix + ch; if (ch < 0 || (val < 0 && (!isNeg || val != MIN_VALUE))) throw new NumberFormatException("invalid character at position " + index + " in " + str); } return isNeg ? -val : val; } }