12/08/2018, 15:35

Tản mạn Autoboxing trong java

Với người lập trình viên java thì hẳn không lạ lẫm gì với kỹ thuật autoboxing, các bạn có thể đã gặp kỹ thuật này rất nhiều nhưng để nắm rõ và phân biệt các dạng autoboxing trong java thì nhiều khi các bạn không để ý tới, nay mình xin chia sẻ với các bạn một cách chi tiết về các dạng autoboxing và ...

Với người lập trình viên java thì hẳn không lạ lẫm gì với kỹ thuật autoboxing, các bạn có thể đã gặp kỹ thuật này rất nhiều nhưng để nắm rõ và phân biệt các dạng autoboxing trong java thì nhiều khi các bạn không để ý tới, nay mình xin chia sẻ với các bạn một cách chi tiết về các dạng autoboxing và ý nghĩa hoạt động của autoboxing trong java như nào nhé?

  1. Autoboxing Khái niệm autoboxing bắt đầu xuất hiện từ java 5, có các nhiều dạng autoboxing như: autoboxing, auto-unboxing. Boxing và autoboxing sử dụng các lớp wraper class một cách thuận lợi. Từ java version 5 trở về trước các bạn muốn tạo ra wrapper class hay unwrapper class thì phải mất khá nhiều bước.
    Integer y = new Integer(123); 	//make it
	int x = y.intValue();  			//unwrap it
	x++;  					//use it
	y = new Integer(x);			//re-wrap it
	System.out.println("y = " + y);	//print it

còn với các version java5 trở lên thì autoboxing đã xuất hiện:

    Integer y = new Integer(123); //make it
	y++;					//unwrap it, increment it, rewrap it
	System.out.println("y = " + y);//print it

Trong ví dụ trên nhiều bạn có thể nhầm rằng một wrapper objec “y” đã bị thay đổi, trong khi đó chúng ta được biết wrapper object là imutable. Vậy là có sự mâu thuẫn ở ví dụ trên phải không. Mình sẽ chứng minh cho các bạn việc wrapper object vẫn là imutable còn sự thay đổi của “y” là cơ chế autoboxing.

    Integer y = 567; 	// make a wrapper
	Integer x = y; 	// assign a second ref
				// var to THE wrapper
		
	System.out.println(y==x); 	// verify that they refer
						// to the same object	
	
	y++;					   // unwrap, use, "rewrap"
	System.out.println(x + " " + y); // print values
						   
	System.out.println(y==x); // verify that they refer
					  // to different objects

out put là: true 567 568 false Như vậy quá trình “y++” sảy ra như thế nào, thực tế compile sẽ thực hiện như sau:

    int x2 = y.intValue();	// unwrap it
	x2++;				// use it
	y = new Integer(x2);	// re-wrap it

2.Boxing, == and equals() Khi nhìn vào == và equals() chắc hẳn các bạn sẽ nghĩ đến phần biệt chúng như thế nào, cái đó mình sẽ không nói đến vì nó rất phổ biến. Điều mình muốn chia sẻ là nó liên quan tới cơ chế autoboxing mà nhiều khi chúng ta hay nhầm lẫn. Tôi có ví dụ như sau:

    Integer i1 = 1000;
	Integer i2 = 1000;
	if(i1 != i2) System.out.println("different objects");
	if(i1.equals(i2)) System.out.println("meaningfully equal");	

Các bạn nghĩ kết quả sẽ in ra như thế nào? Nếu các bạn nghĩ in ra “meaningfully equal” thì sai rồi nhé..^^ sự thật là nó đã in ra cả hai dòng “different objects” và “meaningfully equal”. ví dụ này vẫn đang đúng với suy nghĩ là toán tử “==” và “!=” dùng so sánh biến kiểu nguyên thủy (primitive). Đến vd tiêp theo sẽ có điều hay ho:

    Integer i3 = 100;
	Integer i4 = 100;
	if(i3 == i4) System.out.println("different objects");
	if(i3.equals(i4)) System.out.println("meaningfully equal");

Các bạn có nghĩ nó in ra một dòng “meaningfully equal” ko? thật hay là nó vẫn in ra hai dòng. Tại sao vậy..? i3 và i4 là một kiểu wrapper class mà so sánh “==” vẫn bằng nhau..^^ thật là hư cấu quá..hihi Thực tế là trong java khi biến wrapper object luôn được tạo thông qua autoboxing khi nó có giá trị nằm trong khoảng primitive cụ thể biến là: int (-128 to 127), như vậy vd trên ta khai báo “Integer i3 = 100;” thì trình compile sẽ tự động unwrapper về primitive.

  1. Where boxing can be used Bất cứ khi nào bạn muốn collection nắm giữ cả object và primitive thì bạn sẽ sử dụng wrappers để có thể nó tự động generic autoboxing và unboxing. vd:
class UseBoxing {
	public static void main(String[] args) {
		UseBoxing u = new UseBoxing();
		u.go(5);
	}

	boolean go(Integer i) { // boxes the int it was passed
		Boolean ifSo = true; // boxes the literal
		Short s = 300; // boxes the primitive
		if (ifSo) {
			System.out.println(++s);
		}
		return !ifSo; 		// unboxing
						// unboxes, increments, reboxes
						// unboxes, returns the inverse
	}
}	

Cảm ơn bạn đã theo rõi bài chia sẻ, có gi cần hỏi thêm các bạn có thể commnet phía dưới..^^

0