Trong lập trình Java, ép kiểu (type casting) đóng vai trò quan trọng trong việc xử lý và chuyển đổi giữa các kiểu dữ liệu. Bài viết này Rikkei Academy sẽ giúp bạn hiểu rõ hơn về ép kiểu trong Java, tại sao cần biết về nó, cũng như các loại ép kiểu khác nhau.
Ép kiểu trong Java là gì?
Trước hết, chúng ta nhắc lại 2 loại kiểu dữ liệu trong Java:
- Kiểu dữ liệu nguyên thủy (primitive types) gồm byte, short, int, long, float, double, char và boolean
- Kiểu dữ liệu tham chiếu (reference types) gồm lớp (class), giao diện (interface), mảng (array), và các kiểu dữ liệu tham chiếu được định nghĩa bởi người dùng.
Ép kiểu (type casting) trong Java là quá trình chuyển đổi một kiểu dữ liệu sang một kiểu dữ liệu khác, giúp ta có thể sử dụng các giá trị từ một kiểu dữ liệu trong một ngữ cảnh yêu cầu một kiểu dữ liệu khác. Việc ép kiểu có thể xảy ra tự động hoặc thủ công.
Trong Java, chúng ta có hai loại ép kiểu:
- Ép kiểu tự động (implicit casting)
- Ép kiểu tường minh (explicit casting).
Tại sao cần biết về ép kiểu trong Java?
- Tối ưu hóa bộ nhớ: Ép kiểu giúp quá trình sử dụng bộ nhớ hiệu quả hơn bằng cách chuyển đổi kiểu dữ liệu sang một kiểu dữ liệu với kích thước nhỏ hơn. Ví dụ: lưu trữ một giá trị int nhỏ trong một biến byte
- Tương thích giữa các kiểu dữ liệu: Trong một số trường hợp, ta cần chuyển đổi giữa các kiểu dữ liệu khác nhau để thực hiện các phép toán hoặc gán giá trị. Lúc này, ta sẽ sử dụng ép kiểu.
- Thực hiện phép toán giữa các kiểu dữ liệu khác nhau: Trong quá trình lập trình, chúng ta thường xuyên phải thực hiện các phép toán giữa các kiểu dữ liệu khác nhau. Ép kiểu trong Java giúp chúng ta thực hiện các phép toán này một cách chính xác và hiệu quả.
Ép kiểu ngầm định (implicit casting) trong Java
Trước hết, ta cùng tìm hiểu về ép kiểu ngầm định trong Java
Ép kiểu ngầm định trong Java là gì?
Ép kiểu ngầm định (implicit casting hay widening casting) là quá trình chuyển đổi tự động giữa các kiểu dữ liệu trong Java khi các toán tử hoặc phép tính được thực hiện trên các biến có các kiểu dữ liệu khác nhau. Ép kiểu tự động xảy ra khi ta gán một giá trị có kiểu dữ liệu nhỏ hơn sang một kiểu dữ liệu lớn hơn. Ví dụ: Java tự động chuyển đổi giá trị từ kiểu int sang kiểu long khi gán một giá trị int cho một biến long.

Ép kiểu ngầm định không áp dụng kiểu dữ liệu tham chiếu và được thực hiện bởi trình biên dịch Java theo một tập luật cụ thể, gọi là “tập luật ép kiểu” (casting rules).
Cú pháp:
<kiểu dữ liệu mới> biến = biểu thức; |
Trường hợp sử dụng ép kiểu ngầm định trong Java
Ép kiểu ngầm định thường xảy ra trong các trường hợp sau:
- Gán giá trị của một biến kiểu dữ liệu nguyên thủy nhỏ hơn cho một biến có kiểu dữ liệu nguyên thủy lớn hơn.
- Thực hiện phép toán giữa hai kiểu dữ liệu nguyên thủy khác nhau. Kết quả của phép toán sẽ có kiểu dữ liệu lớn hơn trong hai kiểu dữ liệu tham gia phép toán.
Các quy tắc ép kiểu ngầm định
Một số quy tắc cần tuân theo khi thực hiện ép kiểu ngầm định trong Java:
- Chỉ có thể thực hiện ép kiểu tự động giữa các kiểu dữ liệu nguyên thủy, không thực hiện với dữ liệu tham chiếu
- Ép kiểu tự động chỉ xảy ra khi gán giá trị của một kiểu dữ liệu nhỏ hơn sang một kiểu dữ liệu lớn hơn.
- Khi thực hiện phép toán giữa các kiểu dữ liệu khác nhau, các kiểu dữ liệu được tự động chuyển đổi thành kiểu dữ liệu có độ ưu tiên cao nhất trong các kiểu dữ liệu đó.
Lưu ý: Kiểu boolean không thể ép kiểu tự động sang các kiểu dữ liệu khác.
- Khi thực hiện phép toán giữa hai kiểu dữ liệu nguyên thủy khác nhau, kết quả của phép toán sẽ có kiểu dữ liệu lớn hơn trong hai kiểu dữ liệu tham gia phép toán.
Ví dụ:
public class WideningCastingExample {
public static void main(String[] args) { // khai báo biến kiểu int int myInt = 10; // chuyển đổi kiểu int sang kiểu double double myDouble = myInt; // in ra kết quả System.out.println(“Giá trị của biến myInt là: ” + myInt); System.out.println(“Giá trị của biến myDouble là: ” + myDouble); } } //Giá trị của biến myInt là: 10 //Giá trị của biến myDouble là: 10.0 |
Ép kiểu tường minh (explicit casting) trong Java
Để chuyển đổi dữ liệu trong Java, ngoài ép kiểu ngầm định, chúng ta có thể sử dụng ép kiểu tường minh.
Ép kiểu tường minh là gì?
Ép kiểu tường minh (explicit casting hay narrowing casting) là quá trình chuyển đổi một kiểu dữ liệu sang một kiểu dữ liệu khác bằng cách sử dụng toán tử ép kiểu. Toán tử ép kiểu được biểu diễn bằng cách đặt kiểu dữ liệu muốn chuyển đổi trước giá trị cần chuyển đổi. Ví dụ như chuyển đổi một số nguyên sang một số thực, hoặc chuyển đổi một số thực sang một số nguyên.

Khác với ép kiểu ngầm định được thực hiện tự động, ép kiểu tường minh yêu cầu lập trình viên phải thực hiện thủ cộng.
Cú pháp:
<kiểu dữ liệu mới> biến = (<kiểu dữ liệu mới>) biểu thức; |
Trường hợp sử dụng ép kiểu tường minh
Ép kiểu tường minh được sử dụng trong các trường hợp sau:
- Chuyển đổi từ kiểu dữ liệu lớn hơn sang kiểu dữ liệu nhỏ hơn (ví dụ: từ double sang float, từ long sang int, v.v.).
- Chuyển đổi từ kiểu dữ liệu tham chiếu sang kiểu dữ liệu tham chiếu khác không liên quan (ví dụ: từ Object sang String, từ List sang ArrayList, v.v.).
- Chuyển đổi giữa các kiểu dữ liệu không tương thích với nhau.
Các quy tắc ép kiểu tường minh
Dưới đây là các quy tắc cơ bản khi sử dụng ép kiểu tường minh trong Java:
- Chỉ được sử dụng cho các kiểu dữ liệu có cùng kiểu nguyên thủy hoặc các kiểu dữ liệu trình bày trong hiệu suất tương đương.
- Khi ép kiểu tường minh, cần chú ý đến việc mất mát dữ liệu có thể xảy ra nếu giá trị của biến hoặc biểu thức được ép kiểu vượt quá giới hạn của kiểu dữ liệu đích. Ví dụ, khi chuyển đổi số thực sang số nguyên, phần thập phân của số thực sẽ bị mất đi.
- Khi ép kiểu tường minh cho biến, cần đảm bảo rằng kiểu dữ liệu đích có độ lớn đủ để lưu trữ giá trị của biến đó. Nếu giá trị của biến vượt quá giới hạn của kiểu dữ liệu đích, thì kết quả sẽ không chính xác.
- Khi ép kiểu tường minh cho biểu thức, cần chú ý đến thứ tự của các phép tính. Nếu kiểu dữ liệu của các phần tử trong biểu thức khác nhau, thì kết quả của phép tính sẽ không chính xác nếu ta không sử dụng ép kiểu tường minh.
- Khi sử dụng ép kiểu tường minh, cần sử dụng toán tử ép kiểu để đặt kiểu dữ liệu đích trước biến hoặc biểu thức cần ép kiểu. Ví dụ, để ép kiểu một số nguyên sang một số thực, ta sử dụng toán tử ép kiểu (double) trước biến đó.
Ví dụ:
public class ExplicitCastingExample {
public static void main(String[] args) { int i = 10; double d = 3.14159; // Ép kiểu tường minh để chuyển đổi kiểu dữ liệu của biến i sang kiểu double double convertedI = (double) i; // Ép kiểu tường minh để chuyển đổi kiểu dữ liệu của biến double sang kiểu int int convertedD = (int) d; System.out.println(“Giá trị của biến convertedI là: ” + convertedI); System.out.println(“Giá trị của biến convertedD là: ” + convertedD); } } //Giá trị của biến convertedI là: 10.0 //Giá trị của biến convertedD là: 3 |
Ép kiểu giữa các đối tượng và lớp trong Java
Trong lập trình hướng đối tượng (OOP) với Java, ép kiểu giữa các đối tượng và lớp là một kỹ thuật quan trọng giúp điều chỉnh kiểu dữ liệu của đối tượng theo nhu cầu của chương trình. Ép kiểu giữa các đối tượng và lớp cho phép chúng ta sử dụng các đối tượng của một lớp như đối tượng của lớp khác trong mối quan hệ kế thừa giữa các lớp.
Lưu ý: Chúng ta chỉ có thể ép kiểu giữa các đối tượng của các lớp có mối quan hệ kế thừa. Nếu hai lớp không có mối quan hệ kế thừa, chúng ta không thể ép kiểu chúng với nhau.
Phương pháp ép kiểu giữa các lớp
Ép kiểu trong Java giữa các đối tượng và lớp có thể được thực hiện thông qua hai phương pháp Upcasting và downcasting.

- Upcasting là ép kiểu từ lớp con (subclass) sang lớp cha (superclass). Đây là một phép toán an toàn, tức là nó không gây ra bất kỳ lỗi nào và được thực hiện tự động (ngầm định) bởi trình biên dịch Java.
- Downcasting là ép kiểu từ lớp cha (superclass) sang lớp con (subclass). Đây là một phép toán không an toàn, nó có thể gây ra lỗi ClassCastException nếu đối tượng không thuộc kiểu dữ liệu con được chỉ định. Do đó, downcasting phải được thực hiện tường minh bằng cách sử dụng cú pháp ép kiểu, ví dụ: (Subclass) object.
Lưu ý: Xét theo một số ngữ cảnh thì 2 phương pháp này có thể được hiểu tương tự implicit casting và explicit casting, tuy nhiên, nếu 2 phương pháp trong áp dụng cho việc chuyển đổi kiểu dữ liệu thì upcasting và dowcasing áp dụng cho lớp và đối tượng.
Ví dụ:
// Định nghĩa lớp cơ sở Animal
class Animal { public void makeSound() { System.out.println(“The animal makes a sound”); } } // Định nghĩa lớp Dog kế thừa từ lớp Animal class Dog extends Animal { @Override public void makeSound() { System.out.println(“The dog barks”); } public void fetch() { System.out.println(“The dog fetches”); } } public class Main { public static void main(String[] args) { // Tạo đối tượng Dog Dog dog = new Dog(); // Upcasting: Chuyển đổi đối tượng dog từ lớp Dog sang lớp Animal Animal animal = dog; // Gọi phương thức makeSound() của lớp cha (Animal) animal.makeSound(); // Downcasting: Chuyển đổi đối tượng animal từ lớp Animal sang lớp Dog // Yêu cầu thực hiện tường minh bằng cách sử dụng toán tử ép kiểu (Dog) Dog dog2 = (Dog) animal; // Gọi phương thức makeSound() của lớp con (Dog) dog2.makeSound(); // Gọi phương thức fetch() chỉ có trong lớp Dog dog2.fetch(); } } // The dog barks //The dog barks //The dog fetches |
Với kết quả thứ nhất: Khi gọi phương thức makeSound() từ đối tượng animal (đã được upcasting từ đối tượng Dog), phương thức makeSound() của lớp con Dog được gọi thay vì lớp cha Animal. Điều này cho thấy đa hình (polymorphism) trong lập trình hướng đối tượng. Vì vậy, đầu tiên, chương trình in ra “The dog barks”.
Với kết quả thứ 2: Khi thực hiện downcasting và gọi phương thức makeSound() từ đối tượng Dog (dog2). Lần này, phương thức makeSound() của lớp Dog cũng được gọi và in ra “The dog barks”.
Với kết quả thứ 3: Khi gọi phương thức fetch() từ đối tượng Dog (dog2). Phương thức fetch() chỉ có trong lớp Dog, do đó chương trình in ra “The dog fetches”.
Một số ví dụ ép kiểu trong Java
Ép kiểu nguyên thủy sang nguyên thủy double sang int:
public class DoubleToFloatExample {
public static void main(String[] args) { double number = 3.14; float doubleToFloat = doubleToFloat(number); System.out.println(“Số ” + number + ” sau khi chuyển đổi thành float: ” + doubleToFloat); } // Phương thức chuyển đổi từ double sang float public static float doubleToFloat(double number) { return (float) number; } } |
Ép kiểu nguyên thủy sang tham chiếu int sang Integer:
public class IntToStringExample {
public static void main(String[] args) { int number = 42; String numberAsString = intToString(number); System.out.println(“Số ” + number + ” sau khi chuyển đổi thành chuỗi: ” + numberAsString); } // Phương thức chuyển đổi từ int sang String public static String intToString(int number) { return Integer.toString(number); } } |
Ép kiểu từ tham chiếu sang nguyên thủy String sang int:
public class StringToIntExample {
public static void main(String[] args) { String numberStr = “123”; int stringToInt = stringToInt(numberStr); System.out.println(“Chuỗi ‘” + numberStr + “‘ sau khi chuyển đổi thành số: ” + stringToInt); } // Phương thức chuyển đổi từ String sang int public static int stringToInt(String numberStr) { return Integer.parseInt(numberStr); } } |
Ép kiểu từ tham chiếu sang tham chiếu Integer sang String:
public class IntegerToStringExample {
public static void main(String[] args) { Integer number = 42; String integerToString = integerToString(number); System.out.println(“Integer ” + number + ” sau khi chuyển đổi thành chuỗi: ” + integerToString); } // Phương thức chuyển đổi từ Integer sang String public static String integerToString(Integer number) { return number.toString(); } } |
Lưu ý về mất mát dữ liệu khi ép kiểu trong Java
Trong lập trình, ép kiểu trong Java có thể giúp bạn thích nghi với các yêu cầu khác nhau của ứng dụng, tuy nhiên, nếu không cẩn thận, bạn có thể gặp phải mất mát dữ liệu trong quá trình này.
Xử lý các ngoại lệ liên quan đến ép kiểu trong Java
Trong quá trình ép kiểu có thể phát sinh các ngoại lệ khác nhau và dưới đây là một số cách xử lý phổ biến
ClassCastException
Khi thực hiện ép kiểu, đặc biệt là khi làm việc với kiểu dữ liệu tham chiếu, bạn cần phải xử lý ngoại lệ có thể xảy ra. Một trong những ngoại lệ phổ biến nhất liên quan đến ép kiểu là ClassCastException, bạn có thể sử dụng cấu trúc try-catch xử lý ngoại lệ:
try {
SubClass obj = (SubClass) superClassInstance; } catch (ClassCastException e) { System.out.println(“Cannot cast to SubClass: ” + e.getMessage()); } |
Ngoài ra, trước khi thực hiện downcasting, bạn nên kiểm tra xem đối tượng có thể được ép kiểu sang lớp con hay không bằng cách sử dụng toán tử instanceof. Nếu đối tượng thuộc về lớp con, bạn mới tiến hành ép kiểu:
if (superClassInstance instanceof SubClass) {
SubClass obj = (SubClass) superClassInstance; } else { System.out.println(“Cannot cast to SubClass”); } |
NumberFormatException
Ngoại lệ này xảy ra khi bạn cố gắng ép kiểu chuỗi sang một kiểu dữ liệu số (như int, float, double) mà chuỗi đó không đại diện cho một số hợp lệ. Để xử lý NumberFormatException, bạn có thể sử dụng cấu trúc try-catch:
try {
int number = Integer.parseInt(“abc”); } catch (NumberFormatException e) { System.out.println(“Cannot parse the string to an integer: ” + e.getMessage()); } |
NullPointerException
Đây không phải là một ngoại lệ trực tiếp liên quan đến ép kiểu, nhưng có thể xảy ra nếu bạn cố gắng truy cập một phương thức hoặc thuộc tính của đối tượng sau khi ép kiểu mà đối tượng đó là null. Để xử lý NullPointerException, bạn nên kiểm tra xem đối tượng có null không trước khi truy cập phương thức hoặc thuộc tính của nó:
if (object != null) {
// Do something with the object after casting } else { System.out.println(“The object is null”); } |
Nhìn chung, khi gặp phải ngoại lệ liên quan đến ép kiểu, bạn nên sử dụng cấu trúc try-catch để bắt và xử lý ngoại lệ. Ngoài ra, hãy chắc chắn rằng bạn hiểu rõ về kiểu dữ liệu bạn đang làm việc và thực hiện các kiểm tra phù hợp để tránh gây ra lỗi.
Các lưu ý khi sử dụng ép kiểu trong Java
Khi sử dụng ép kiểu trong lập trình, hãy tuân theo các lưu ý sau để giảm thiểu lỗi và tạo ra mã nguồn dễ hiểu hơn:
- Phân biệt ép kiểu ngầm định và tường minh:Hãy sử dụng đúng loại ép kiểu phù hợp với từng trường hợp.
- Kiểm tra trước khi ép kiểu: Trước khi thực hiện ép kiểu, đảm bảo rằng đối tượng có thể được chuyển đổi an toàn sang kiểu dữ liệu mong muốn bằng cách sử dụng từ khóa instanceof trong Java.
- Hạn chế sử dụng ép kiểu không an toàn: Trong một số trường hợp, bạn có thể không biết chính xác kiểu dữ liệu của đối tượng và cần sử dụng ép kiểu không an toàn. Tuy nhiên, hãy hạn chế sử dụng nó và tìm cách thiết kế mã nguồn sao cho kiểu dữ liệu của các đối tượng rõ ràng hơn.
- Sử dụng các phương thức chuyển đổi an toàn: Trong một số trường hợp, thay vì sử dụng ép kiểu, bạn có thể sử dụng các phương thức chuyển đổi an toàn giữa các kiểu dữ liệu. Ví dụ, khi chuyển đổi từ chuỗi sang số nguyên trong Java, sử dụng Integer.parseInt()
- Xử lý ngoại lệ: Như đã đề cập ở trên, hãy sử dụng cấu trúc try-catch để bắt và xử lý các ngoại lệ có thể xảy ra khi ép kiểu. Điều này sẽ giúp mã nguồn của bạn ổn định hơn và giúp bạn xử lý các tình huống không mong muốn.
- Hiểu rõ kiểu dữ liệu sử dụng: Đảm bảo rằng bạn hiểu rõ về kiểu dữ liệu bạn đang làm việc và các quy tắc chuyển đổi giữa chúng.
Kết luận
Như vậy, Rikkei Academy đã cung cấp cho bạn các thông tin chi tiết về Ép kiểu trong Java trên nhiều khía cạnh khác nhau bao gồm khái niệm, phân loại và một số kiến thức quan trọng trong type casting. Bằng cách nắm vững kiến thức về ép kiểu sẽ giúp bạn tiết kiệm được thời gian và công sức xử lý và chuyển đổi giữa các kiểu dữ liệu!
Nếu bạn đang muốn tìm hiểu khóa học lập trình, tham khảo ngay Rikkei Academy! Chương trình được thiết kế tinh gọn với các kiến thức, kỹ năng bám sát thực tế cùng giảng viên luôn hỗ trợ 24/7 sẽ giúp bạn nhanh chóng trở thành lập trình viên trong 6 tháng! Đăng ký để nhận tư vấn miễn phí ngay hôm nay!