Kiểu dữ liệu (2)

Trong bài hướng dẫn này, chúng ta sẽ tiếp tục discuss về kiểu dữ liệu trong Java như: wrapper class, boxing và unboxing, giá trị default, conversion và promotion.

Wrapper class

Wrapper class là các biểu diễn các kiểu dữ liệu nguyên thủy thành các object. Wrapper class được sử dụng để mô tả các giá trị nguyên thủy khi object được yêu cầu. Ví dụ: Java collection chỉ làm việc với các object. Wrapper class cũng có các phương thức hữu ích. Ví dụ, chúng bao gồm các phương thức cho việc convert kiểu dữ liệu. Việc đặt kiểu dữ liệu nguyên thủy vào wrapper class được gọi là boxing. Quá trình ngược lại gọi là unboxing.
Về nguyên tắc chung, chúng ta sử dụng wrapper class khi chúng ta không thể sử dụng kiểu dữ liệu nguyên thủy. Ngược lại, chúng ta sử dụng kiểu dữ liệu nguyên thủy. Các class wrapper là bất biến. Chúng được tạo 1 lần và không thể thay đổi chúng. Kiểu dữ liệu nguyên thủy nhanh hơn kiểu box (wrapper class). Trong khoa học tính toán và xử lí số lớn, wrapper class có thể khiến cho đạt được 1 performance đáng kể.

Kiểu dữ liệu nguyên thủy Wrapper Class Đối số hàm tạo
byte Byte byte or String
short Short short or String
int Integer int or String
long Long long or String
float Float float, double or String
double Double double or String
char Character char
boolean Boolean boolean or String

Table: Kiểu dữ liệu nguyên thủy và wrapper class tương ứng

Class Integer đóng gói giá trị của kiểu dữ liệu nguyên thủy int thành object. Nó bao gồm các hằng số và các phương thức hữu ích liên quan việc xử lí kiểu int.

package net.vncoding;


public class IntegerWrapper {

    public static void main(String[] args) {
        
        int a = 55;       
        Integer b = new Integer(a);
        
        int c = b.intValue();
        float d = b.floatValue();
        
        String bin = Integer.toBinaryString(a);
        String hex = Integer.toHexString(a);
        String oct = Integer.toOctalString(a);        
        
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
        
        System.out.println(bin);
        System.out.println(hex);
        System.out.println(oct);            
    }
}

Ví dụ minh họa sử dụng Integer wrapper class.

int a = 55;

Dòng lệnh này tạo biến số nguyên kiểu nguyên thủy int.

Integer b = new Integer(a);

Đối tượng kiểu Integer wrapper được tạo từ kiểu dữ liệu nguyên thủy int.

int c = b.intValue();
float d = b.floatValue();

Phương thức intValue() convert object Integer thành kiểu dữ liệu nguyên thủy int. Phương thức floatValue() trả về kiểu dữ liệu float.

String bin = Integer.toBinaryString(a);
String hex = Integer.toHexString(a);
String oct = Integer.toOctalString(a); 

3 phương thức trả về số nguyên kiểu binary, hexa, octal.

Java - Integer wrapper class
Java – Integer wrapper class

Collection là công cụ rất mạnh giành cho làm việc với nhóm các object. Kiểu dữ liệu nguyên thủy không nằm trong Java collection. Sau khi chúng ta đóng gói giá trị nguyên thủy, chúng ta có thể đặt chúng vào collection.

package net.vncoding;


import java.util.ArrayList;
import java.util.List;

public class Numbers {

    public static void main(String[] args) {
        
        List<Number> ls = new ArrayList<>();
        
        ls.add(1342341);
        ls.add(new Float(34.56));
        ls.add(235.242);
        ls.add(new Byte("102"));
        ls.add(new Short("1245"));
       
        for (Number n : ls) {
            
            System.out.println(n.getClass());
            System.out.println(n);
        }
    }
}

Trong ví dụ này, chúng ta đặt nhiều số vào ArrayList. ArrayList là dữ liệu kiểu dynamic, có thể thay đổi được kích thước.

List<Number> ls = new ArrayList<>();

Đối tượng ArrayList được tạo. Trong dấu ngoặc nhọn <>, chúng ta chỉ định kiểu dữ liệu mà container lưu trữ.
Number là class cơ sở trừu tượng (abstract base class) cho 5 số kiểu dữ liệu nguyên thủy trong Java.

ls.add(1342341);
ls.add(new Float(34.56));
ls.add(235.242);
ls.add(new Byte("102"));
ls.add(new Short("1245"));

Chúng ta add 5 số vào collection. Chú ý rằng, giá trị nguyên và dấu phẩy động không được đóng gói. Do compiler có thể auto đóng gói kiểu dữ liệu int và double.

for (Number n : ls) {
    System.out.println(n.getClass());
    System.out.println(n);
}

Chúng ta duyệt container và in tên class và giá trị của mỗi phần tử.

Kết quả:

Java - Collection
Java – Collection

Boxing

Convert từ kiểu dữ liệu nguyên thủy sang kiểu object, được gọi là boxing. Unboxing là việc convert ngược lại, từ object sang kiểu dữ liệu nguyên thủy.

package net.vncoding;


public class BoxingUnboxing {

    public static void main(String[] args) {
        
        long a = 124235L;        
        
        Long b = new Long(a);
        long c = b.longValue();
        
        System.out.println(c);
    }
}

Trong ví dụ này, chúng ta đóng gói giá trị kiểu long thành object long và ngược lại.

Long b = new Long(a);

Dòng này thực hiện boxing

long c = b.longValue();

Dòng này thực hiện unboxing.

Autoboxing

Java SE 5 đã giới thiệu autoboxing. Autoboxing là auto convert giữa kiểu dữ liệu nguyên thủy và các object wrapper class tương ứng. Autoboxing giúp cho việc lập trình dễ ràng hơn. Lập trình viên không cần thực hiện convert thủ công.
Autoboxing và unboxing được thực hiện khi 1 giá trị là kiểu dữ liệu nguyên thủy và còn lại là wrapper class trong các trường hợp sau:
– Phép gán
– Truyền tham số cho phương thức
– Trả về giá trị từ phương thức
– Phép toán so sánh
– Phép toán số học

Integer i = new Integer(50);

if (i < 100) {
   ...
}

Trong ngoặc () của câu lệnh if, đối tượng Integer được so sánh với kiểu int (100). Đối tượng Integer được auto convert thành kiểu dữ liệu nguyên thủy int. Quá trình này được gọi là auto unboxing.

Autoboxing.java

package net.vncoding;

public class Autoboxing {
    
    private static int cube(int x) {
        
        return x * x * x;
    }

    public static void main(String[] args) {
        
        Integer i = 10;
        int j = i;
        
        System.out.println(i);
        System.out.println(j);        
        
        Integer a = cube(i);
        System.out.println(a);    
    } 
}

Automatic boxing and automatic unboxing được mình họa như ví dụ trên.

Integer i = 10;

Trình biên dịch Java tự động thực hiện boxing dòng code này. Giá trị nguyên (10) được boxing tự động thành kiểu Integer.

int j = i;

Đây là quá trình unboxing. Convert từ kiểu Integer thành kiểu dữ liệu nguyên thủy int.

Integer a = cube(i);

Khi chúng ta truyền đôi số kiểu Integer vào phương thức cube(), auto unboxing được thực hiện. Còn khi chúng ta trả về giá trị, auto boxing được thực hiện bởi vì kiểu int được convert thành kiểu Integer.
Java không support chồng toán tử (Operator Overloading), khác với C++. Khi chúng ta thực hiện phép toán số học trên wrapper class, auto boxing được thực hiện bởi trình biên dịch.

Autoboxing2.java

package net.vncoding;

public class Autoboxing2 {

    public static void main(String[] args) {
        
        Integer a = new Integer(5);
        Integer b = new Integer(7);
        
        Integer add = a + b;
        Integer mul = a * b;
        
        System.out.println(add);
        System.out.println(mul);    
    }
}

Chúng ta có 2 giá trị Integer. Thực hiện phép cộng và nhân a và b.

Integer add = a + b;
Integer mul = a * b;

Khác với Ruby, C#, Phython, C++, Java không support chồng toán tử. Khi thực thi 2 dòng code này, trình biên dịch gọi phương thức intValue() và convert wrapper class thành kiểu int, sau đó convert int thành wrapper class bởi việc gọi phương thức valueOf().

Autoboxing and object interning

Be the first to comment

Leave a Reply

Your email address will not be published.

*