import java.util.*;

/** Wrapper classes: the eight types, boxing, the Integer cache, unboxing NPEs, equals traps, NaN and -0.0. */
public class WrapperTraps {
    public static void main(String[] args) {
        System.out.println("== 1. the eight wrappers ==");
        System.out.println("byte    Byte       " + Byte.MIN_VALUE + " .. " + Byte.MAX_VALUE);
        System.out.println("short   Short      " + Short.MIN_VALUE + " .. " + Short.MAX_VALUE);
        System.out.println("int     Integer    " + Integer.MIN_VALUE + " .. " + Integer.MAX_VALUE);
        System.out.println("long    Long       " + Long.MIN_VALUE + " .. " + Long.MAX_VALUE);
        System.out.println("float   Float      " + Float.MIN_VALUE + " .. " + Float.MAX_VALUE);
        System.out.println("double  Double     " + Double.MIN_VALUE + " .. " + Double.MAX_VALUE);
        System.out.println("char    Character  " + (int) Character.MIN_VALUE + " .. " + (int) Character.MAX_VALUE);
        System.out.println("boolean Boolean    " + Boolean.FALSE + ", " + Boolean.TRUE);

        System.out.println("\n== 2. the Integer cache trap ==");
        Integer a = 127, b = 127, c = 128, d = 128;
        System.out.println("127 == 127 : " + (a == b));
        System.out.println("128 == 128 : " + (c == d) + "   equals: " + c.equals(d));
        System.out.println("Integer.valueOf(127) == Integer.valueOf(127): " + (Integer.valueOf(127) == Integer.valueOf(127)));
        System.out.println("Long cache also -128..127: " + (Long.valueOf(127) == Long.valueOf(127)) + " / " + (Long.valueOf(128) == Long.valueOf(128)));
        System.out.println("Boolean and Byte are cached too  : " + (Boolean.valueOf(true) == Boolean.valueOf(true)) + " " + (Byte.valueOf((byte) 5) == Byte.valueOf((byte) 5)));
        System.out.println("Double is never cached : " + (Double.valueOf(1.0) == Double.valueOf(1.0)));

        System.out.println("\n== 3. autoboxing is a method call ==");
        Integer boxed = 42;               // compiles to Integer.valueOf(42)
        int unboxed = boxed;              // compiles to boxed.intValue()
        System.out.println("boxed=" + boxed + " unboxed=" + unboxed);

        System.out.println("\n== 4. unboxing null throws NullPointerException ==");
        Map<String, Integer> stock = new HashMap<>();
        try { int n = stock.get("pens"); System.out.println(n); }
        catch (NullPointerException e) { System.out.println(e.getMessage()); }
        boolean flag = true;
        try { Integer r = flag ? stock.get("pens") : 0; System.out.println(r); }
        catch (NullPointerException e) { System.out.println("ternary: " + e.getMessage()); }

        System.out.println("\n== 5. equals() is type-strict ==");
        System.out.println("Long.valueOf(5).equals(5)  : " + Long.valueOf(5).equals(5) + "   (5 boxes to Integer)");
        System.out.println("Long.valueOf(5).equals(5L) : " + Long.valueOf(5).equals(5L));
        System.out.println("Integer 5 == long 5L (unboxes): " + (Integer.valueOf(5) == 5L));

        System.out.println("\n== 6. NaN and -0.0 ==");
        double nan = Double.NaN;
        System.out.println("NaN == NaN                   : " + (nan == nan));
        System.out.println("Double.valueOf(NaN).equals(NaN): " + Double.valueOf(nan).equals(nan));
        System.out.println("0.0 == -0.0                  : " + (0.0 == -0.0));
        System.out.println("Double.valueOf(0.0).equals(-0.0): " + Double.valueOf(0.0).equals(-0.0));

        System.out.println("\n== 7. parsing and comparing ==");
        System.out.println("parseInt(\"ff\", 16) = " + Integer.parseInt("ff", 16) + ", toBinaryString(10) = " + Integer.toBinaryString(10) + ", MAX+1 = " + (Integer.MAX_VALUE + 1));
        try { Integer.parseInt("12a"); } catch (NumberFormatException e) { System.out.println("parseInt(\"12a\"): " + e.getMessage()); }
        System.out.println("Integer.compare(3, 7) = " + Integer.compare(3, 7) + ", Integer.sum(3, 7) = " + Integer.sum(3, 7));
        System.out.println("Character.isDigit('7')=" + Character.isDigit('7') + " getNumericValue('z')=" + Character.getNumericValue('z'));
    }
}
