Widening and Boxing Java primitives

前端 未结 5 627
一生所求
一生所求 2020-12-07 01:33

Widening and Boxing Java primitives.

I know it is not possible to widen a wrapper class from one to another as they are not from the same inheritence tree. Why thou

相关标签:
5条回答
  • 2020-12-07 01:53

    In Java, Boxing + Widening is allowed, but not Widening + Boxing.. For goInteger to be accepted, first widening of primitive datatype (byte -> int) is required, which ok and then Boxing is required (int -> Integer). Please find the 5 golden ruled of Widening, Boxing and Vararg:

    1. Primitive Widening > Boxing > Varargs.
    2. Widening and Boxing (WB) not allowed.
    3. Boxing and Widening (BW) allowed.
    4. While overloading, Widening + vararg and Boxing + vararg can only be used in a mutually exclusive manner i.e. not together.
    5. Widening between wrapper classes not allowed

    I hope this will help you. With regards, Sudipta Deb.

    0 讨论(0)
  • 2020-12-07 01:57

    Why? Because boxing / autoboxing is only some compiler sugar and not a new type system. It's badly designed and causes trouble at least as often as it simplifies things.

    But here are some workarounds for your compile error:

    goInteger((int) b);
    
    // these are equivalent
    goInteger(((Byte) b).intValue());
    goInteger(Byte.valueOf(b).intValue());
    
    0 讨论(0)
  • 2020-12-07 01:57

    If we allow too many magic conversions, it'll get very confusing.

    The existing conversion rules are already more than people care to understand. Even the language spec got it wrong! See this funny example Java casting: is the compiler wrong, or is the language spec wrong, or am I wrong?

    0 讨论(0)
  • 2020-12-07 02:00

    I think the order is pretty fascinating. I made out the following playground to see every possible combination. This are my functions:

    static void doSomeThing(short i) {
        System.out.println("short");
    }
    
    static void doSomeThing(short... i) {
        System.out.println("short...");
    }
    
    static void doSomeThing(Short i) {
        System.out.println("SHORT");
    }
    
    static void doSomeThing(Short... i) {
        System.out.println("SHORT...");
    }
    
    static void doSomeThing(long i) {
        System.out.println("long");
    }
    
    static void doSomeThing(long... i) {
        System.out.println("long...");
    }
    
    static void doSomeThing(Long i) {
        System.out.println("LONG");
    }
    
    static void doSomeThing(Long... i) {
        System.out.println("LONG...");
    }
    
    static void doSomeThing(int i) {
        System.out.println("int");
    }
    
    static void doSomeThing(int... i) {
        System.out.println("int...");
    }
    
    static void doSomeThing(Integer i) {
        System.out.println("INTEGER");
    }
    
    static void doSomeThing(Integer... i) {
        System.out.println("INTEGER...");
    }
    
    static void doSomeThing(Object i) {
        System.out.println("Object");
    }
    
    static void doSomeThing(Object... i) {
        System.out.println("Object...");
    }
    

    Rules:

     1.Searches for exactly the same type (int -> int)
     2.Widening (int -> long)
     3.Boxing (int-> Integer, it is NEVER possible to implicit box AND wide (int -> Long NOT possible without cast))
     !!Multiple boxing go BEFORE var args!!
     int -> Object will be chosen before int -> int...
     4.Var args (int -> int...)
     5.Widening + var args (int -> long...)
     6.Boxing + var args (int -> Integer...)
     7.Boxing + widening + var args (int -> Object...)
    
    public class Main{
    
        public static void main(String...args) {
            //primitive int
            int i = 0;
            doSomeThing(i); //int
            //commented out doSomeThing(int i){}
            doSomeThing(i); //long. It is not possible to narrow, so short, short... Short and Short... will NEVER be called when the input is larger than a short.
            //commented out doSomeThing(long i){}
            doSomeThing(i); //INTEGER
            //commented out doSomething(Integer i){}
            doSomeThing(i); //Object. Notice that there can be multiple boxing before moving to var args
                                //Error occured: compiler if confused: can either execute int..., long..., Object... or Integer...
            //Object... and Integer... are commented out, because in the real world int... will be called first
            doSomeThing(i); //int...
            //commented out int...
            doSomeThing(i); //long...
            //commented out long... and uncommented Integer...
            doSomeThing(i); //Integer...
            //commented out Integer... and uncommented Object...
            doSomeThing(i); //Object...
    
                    //Integer
            //Integer
            Integer i = new Integer(0);
            doSomeThing(i); //INTEGER
            //commented out doSomeThing(Integer i)
            doSomeThing(i); //Object
            //commented out doSomeThing(Object i)
            doSomeThing(i); //int
            //commented out doSomeThing(int i)
            doSomeThing(i); //long so NOT int... it goes widening again
            //commented out doSomeThing(long i)
                            //Error occured: compliler refused: not both have int..., long..., Integer... and Object...
            //int... and long... are commented out
            doSomeThing(i); //INTEGER...
            //commented out doSomeThing(Integer... i)
            doSomeThing(i); //Object...
            //commented out doSomeThing(Object... i)
            //uncommented doSomeThing(int... and long...)
            doSomeThing(i); //int...
            //uncommented doSomeThing(int... i)
            doSomeThing(i); //long...
        }
    
    0 讨论(0)
  • 2020-12-07 02:16

    Short answer

    The java language only supports some level of carelessness.

    Longer answer

    I believe that autoboxing was added to support developer carelessness. Specifically in situations like this: "I need an Integer as a parmeter to the method I want to call, but I have an int. Somehow, new Integer(int) never pops into my head. Instead, I'll just send an int and the java compiler will do the new Integer() call for me. Thanks java carelessness support group!"

    The folks designing autoboxing were willing to support 1 level of carelessness (int => Integer and back), but were not willing to support auto casting of smaller primitive types to larger primitive types in conjunction with automatic creation and extration from primitive type wrapper classes. I suspect the descision matrix for this would be somewhat larger than the decision matrix for the current autoboxing scheme.

    0 讨论(0)
提交回复
热议问题