开发者

autoboxing and generics

I am actually confused on the bo开发者_高级运维th the topics, can anyone explain me.

ArrayList<Long> queryParms = new ArrayList<Long>();
  1. Is the above one called generics or autoboxing and what is unboxing?
  2. Is it a best practice?
  3. Some say Autoboxing is evil thing.
  4. If i use generics, can i avoid autoboxing and unboxing?


  1. The above is an example of generics. Auto-boxing would be the automatic conversion, by the compiler, of a primitive type in a wrapper type, and vice versa. In your case, for example, from a long variable in a Long variable:

    long param = 13L;
    queryParms.add(param);
    
  2. Using generics? Yes. It allows you to specify what your list will contain. You should use them. Using auto-boxing? Yes, it simplifies the code, and you don't have to worry about conversions between primitive variable types into wrapper (and vice-versa).

  3. Auto-boxing isn't evil (IMHO). They are some corner cases in which auto-boxing can be very annoying, but if you know how it works, you shouldn't have to worry about it. Here is the Sun (now Oracle) paper on auto-boxing, if you need to know more about it.

  4. If you want to create a list that contains wrappers (in your case, Long), you'll have to deal with type conversion. You can use explicit type conversion, or you can use auto-boxing.


Autoboxing is when a primitive is automatically converted into an object. For example:

Long autoboxedLong = 3;

Note the upper case L, making autoboxedLong an object instead of a primitive.

The reverse is auto-unboxing, which allows you to write:

long autounboxedLong = autoboxedLong;

i.e. you're automatically converting an object into a primitive. However this is dangerous, because autoboxedLong can be null. Then this code would throw a NullPointerException.

Your example is not about autoboxing, but autoboxing comes into play when you insert objects into your list. You can do:

queryParams.add(1);

and autoboxing would automatically box your primitive long 1 into a Long object.


No the above is not called autoboxing.When you do

queryParms.add(22l);//here primitive type 22 is converted to wrapper class Long type.This      
                    //is called autoboxing.


You example creates a ArrayList with generic type Long. So the list will contain objects of type long. Outoboxing makes primitives from objects and vice versa. So you can use your list like:

long x = queryParms.get(0);

or

queryParams.add(4L);


Within Java 5.0, wrapper classes have become easier to use. Java 5.0 introduced automatic conversion between a primitive type and the corresponding wrapper class.

From primitive type to it corresponse wrapper class is called autoboxing, the reverse process is called unboxing. Autoboxing and unboxing also apply to methods calls. For example, you can pass an argument of type int to a method that has a formal parameter of type Integer.

  • A NullpointerException exception occurs When unboxing an null wrapper class's reference to its primitive type. For example, the code will compile but it will throw a NullpointerException at runtime.

    Long  L = null;    long  l = L;    ...
    
  • Boxing conversion converts values of primitive type to corresponding values of reference type. But the primitive types can not be widened/Narrowed to the Wrapper classes and vice versa. For example,

    byte b = 43; Integer I1 = 23; //Constant integer value Integer I2 = (int)b; //Cast to int type Long L1 = 23; //compile error because 23 is integer value Long L2 = (Long)23; //can not cast integer value to Long wrapper class Long L3 = 23L; Long L4 = (long)23;

This restriction is also applied to method invocation:

public class MyClass
{
    public void method(Long i)
    {
        System.out.println("Here");

    }
    public static void main(String[] args)
    {
        MyClass s = new MyClasslass();
        //s.method(12);
        // error        s.method(12L);
        // ok
    }

}
•When invoking a method from multiple overloading methods, For the matching method process, the Java compiler will perferance the order of primitive types (Widening Primitive Conversion), wrapper class (Boxing Conversion), and var-args. For example,
public class MyClass
{
    public void method(Long x, Long y)
    {
        System.out.println("method(Long x, Long y)");

    }
    public void method(long x, long y)
    {
        System.out.println("method(long x, long y)");

    }
    public void method(long... x)
    {
        System.out.println("method(long... x)");

    }
    public static void main(String[] args)
    {
        long x, y;
        x = y = 0;
        MyClass s = new MyClass();
        s.method(x, y);

    }

}

The result is method(long x, long y). The Java compiler will check for the matching primitive types, then it will search for the Wrapper types.

public class MyClass
{
    public void method(Long x, Long y)
    {
        System.out.println("method(Long x, Long y)");

    }
    public void method(int x, int y)
    {
        System.out.println("method(int x, int y)");

    }
    public void method(long... x)
    {
        System.out.println("method(long... x)");

    }
    public static void main(String[] args)
    {
        long x, y;
        x = y = 0;
        MyClass s = new MyClass();
        s.method(x, y);

    }

}

The result is method(Long x, Long y). The Java compiler gives preferance to the matching Wrapper class method signature other than the primitive varargs method.

public class MyClass
{
    public void method(Double x, Double y)
    {
        System.out.println("method(Double x, (Double y)");

    }
    public void method(int x, int y)
    {
        System.out.println("method(int x, int y)");

    }
    public void method(long... x)
    {
        System.out.println("method(long... x)");

    }
    public static void main(String[] args)
    {
        long x, y;
        x = y = 0;
        MyClass s = new MyClass();
        s.method(x, y);

    }

}

The result is method(long ...x). The compiler will not narrow down "long" primitive value to "int"; Also, it can not winden long to Double class. Only the var-args method can be used.

public class MyClass
{
    public void method(Long x, Long y)
    {
        System.out.println("method(Long x, Long y)");

    }
    public static void main(String[] args)
    {
        int x, y;
        x = y = 0;
        MyClass s = new MyClass();
        s.method(x, y);

    }

}

The arguments can not winden to "long" and then box to "Long". You will get compile error.

  • In order to save memory, two instances of the following wrapper objects will always be == when their primitive values are the same. Please read Why does the autoboxing conversion sometimes return the same reference?
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜