Hotline: 0919 365 363; Email: daotao@r2s.edu.vn

Generic trong java – Những điều cần biết

Generic trong java – Những điều cần biết

Kiến thức hữu ích

Generic trong java – Những điều cần biết

Generic trong Java là một tính năng cho phép sử dụng kiểu dữ liệu động được thông qua khi tạo đối tượng hoặc khai báo một lớp. Khi sử dụng Generic, ta có thể tái sử dụng và tối ưu hóa mã nguồn, đồng thời giảm thiểu lỗi do kiểu dữ liệu không chính xác hơn.

Vậy học về Generic như thế nào? Bắt đầu từ đâu? Tìm hiểu với chúng tôi thật chi tiết cùng R2S nhé!

Generic trong java là gì?

Generic trong java
Generic trong java là gì?

Trước khi học về những thao tác và cú pháp với Generic trong java, mời bạn hãy cùng với chúng tôi

Generics là thuật ngữ chỉ tham số hóa kiểu dữ liệu, rất quan trọng trong việc tạo ra và sử dụng class, interface và method với nhiều kiểu dữ liệu khác nhau. Khi một class, interface hoặc method được thực hiện trên một kiểu tham số cụ thể, ta gọi nó là generic. 

Generics là cách thức lập trình tổng quát cho phép một object hoạt động với nhiều kiểu dữ liệu khác nhau.

Một số ví dụ về Generic trong java

Dưới đây là một số ví dụ dễ hiểu nhất về Generic trong java mà bạn có thể tham khảo:

Ví dụ 1

  • Đến mục package generic 
  • Tạo class tên SampleGeneric1  
  • Sử dụng ArrayList với các kiểu dữ liệu khác nhau
  • Bạn sẽ nhận được:
package generic;
import java.util.ArrayList;
/**
 *
 * @author giasutinhoc.vn
 */
public class SampleGeneric1 {
 public static void main(String[] args) {
   // Sử dụng ArrayList với các kiểu dữ liệu khác nhau
   ArrayList mylist = new ArrayList();

   // Thêm vào array
   mylist.add(10);
   mylist.add("Hello");
   mylist.add(true);
   mylist.add(15.75);

   // Lấy ra
   int i = (Integer)mylist.get(0);
   String s = (String)mylist.get(1);
   boolean b = (boolean)mylist.get(2);
   double d = (double)mylist.get(3);

   // Hiển thị
   System.out.println("Phan tu thu nhat la: " + i);
   System.out.println("Phan tu thu hai la: " + s);
   System.out.println("Phan tu thu ba la: " + b);
   System.out.println("Phan tu thu tu la: " + d);
 }
}

Ví dụ 2 – Generic trong java

  • Sử dụng ArrayList với các kiểu dữ liệu Integer như sau:
Ví dụ về generic
Ví dụ về generic
  • Đến mục package generic
  • Tạo class tên SampleGeneric2 
package generic;
import java.util.ArrayList;
/**
 *
 * @author giasutinhoc.vn
 */
public class SampleGeneric2 {
 public static void main(String[] args) {
   // Sử dụng ArrayList với các kiểu dữ liệu Integer
   ArrayList<Integer> mylist = new ArrayList<Integer>();

   // Thêm vào array
   mylist.add(10);
   mylist.add("Hello");  //Error

   // Lấy ra
   int i = mylist.get(0);

   // Hiển thị
   System.out.println("So nguyen: " + i);
  }
}

Sử dụng Generics, người lập trình có thể thực hiện các thuật toán tổng quát với các kiểu dữ liệu khác nhau theo sự lựa chọn của mình. Việc này giúp làm rõ nội dung và tạo sự dễ hiểu hơn cho đoạn code của chương trình.

Khái niệm Generic Methods – Generic trong java là gì?

Generic Methods trong Java là các phương thức có tham số kiểu dữ liệu chung hoặc có thể là kiểu dữ liệu chung cho kiểu trả về của phương thức. 

Generic Methods sẽ cho phép người lập trình có thể sử dụng chung một phương thức để xử lý các kiểu dữ liệu khác nhau, giúp tối ưu hóa mã nguồn và tăng tính linh hoạt của chương trình.

Quy ước đặt tên tham số kiểu cho Generic trong Java

Ký tự viết tắt Viết đầy đủGiải thích
EElementphần tử
KKeykhóa
VValue giá trị
TTypekiểu dữ liệu
NNumber số

Ví dụ minh họa

Tạo class tên GenericMethodTest trong package generic như sau:

package generic;
/**
 *
 * @author giasutinhoc.vn
 */
public class GenericMethodTest {
 // generic method printArray
 public <T> void printArray(T[] inputArray) {
  // Display array elements
   for ( T element : inputArray ){
    System.out.print(element);
   }
   System.out.println();
 }

 public static void main( String args[] ){
   // Create arrays of Integer, Double and Character
   Integer[] intArray = { 1, 2, 3, 4, 5 };
   Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
   Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };

   // Create object
   GenericMethodTest gmt = new GenericMethodTest();
   System.out.println( "Array integerArray contains:" );
   gmt.printArray( intArray ); // pass an Integer array

   System.out.println( "\nArray doubleArray contains:" );
   gmt.printArray( doubleArray ); // pass a Double array

   System.out.println( "\nArray characterArray contains:" );
   gmt.printArray( charArray ); // pass a Character array
 }
}

Khi bạn chạy chương trình sẽ cho kết quả như sau:

Ví dụ về generic
Ví dụ về generic

Generic Classes trong java là gì?

Generic Classes là các lớp được tham số hóa kiểu dữ liệu, cho phép sử dụng các kiểu dữ liệu khác nhau khi tạo đối tượng hoặc khai báo một lớp. Generic Classes sẽ giúp tối ưu hóa mã nguồn, giảm thiểu lỗi do kiểu dữ liệu không chính xác và tăng tính linh hoạt của chương trình.

Ví dụ tạo class tên Box trong package generic trong java

package generic;
/**
 *
 * @author giasutinhoc.vn
 */
public class Box<T> {
 private T t;
 public void add(T t) {
   this.t = t;
 }

 public T get() {
   return t;
 }

 public static void main(String[] args) {
  Box<Integer> intBox = new Box<Integer>();
  Box<String> strBox = new Box<String>();

  intBox.add(new Integer(10));
  strBox.add(new String("Hello World"));

  System.out.println("Integer Value: " + intBox.get());
  System.out.println("String Value: " + strBox.get());
 }
}

Kết quả sau khi chạy chương trình Generic trong java là:

Integer Value :10 
String Value :Hello World 

Các ký tự đại diện generic (Wildcards) cần biết

Các ký tự đại diện generic (Wildcards) cần biết
Các ký tự đại diện generic (Wildcards) cần biết

Ký tự đại diện <?>

Xét ví dụ sau:

private boolean checkEquals(RestricExample<T> e) {
 if(number.doubleValue() == e.number.doubleValue()) {
   return true;
 }

 return false;
}

 private boolean checkEquals2(RestricExample<?> e) {
  if(number.doubleValue() == e.number.doubleValue()) {
   return true;
  }

  return false;
 }

 Trả về phương thức checkEquals chỉ cho phép tham số e có cùng kiểu dữ liệu với biến number. Trong khi đó, phương thức checkEquals2 có thể chấp nhận tham số e là kiểu dữ liệu khác với biến number. 

Sử dụng ký tự đại diện “<? extends type>” cho phép chấp nhận bất kỳ đối tượng nào kế thừa hoặc là đối tượng của type.

Ví dụ minh họa

public void processElement(List<? extends A> elements){
 ...
}

Trong đó:

Các ký tự đại diện generic (Wildcards) cần biết
Các ký tự đại diện generic (Wildcards) cần biết

Sử dụng phương thức processElement (Chấp nhận bất ký đối tượng nào miễn là đối tượng này phải kế thừa từ lớp A hoặc đối tượng của A => ClassA, ClassB và ClassC)

List<A> listA = new ArrayList<A>();
processElement(listA);

List<B> listB = new ArrayList<B>();
processElement(listB);

List<C> listC = new ArrayList<C>();
processElement(listC);

Ký tự đại diện <? super type> chấp nhận bất ký đối tượng nào miễn là đối tượng này là cha của type hoặc đối tượng của type

Ví dụ:

public void processElement(List<? super A> elements){
 ...
}
List<A> listA = new ArrayList<A>();
processElement(listA);

List<Object> listO = new ArrayList<Object>();
processElement(listO);

Giới hạn kiểu dữ liệu với ký tự đại diện <? extends type> như thế nào?

Trong một số trường hợp, chúng ta muốn giới hạn kiểu dữ liệu được sử dụng cho các tham số. 

Chẳng hạn, khi tạo phương thức chỉ chấp nhận tham số là số nguyên hoặc số thực. Điều này giúp tăng tính chính xác và đảm bảo rằng đầu vào chương trình được đúng và chính xác.

package generic;
/**
 *
 * @author giasutinhoc.vn
 */
public class RestricExample <T extends Number> {
 private T number;
 public RestricExample(T number) {
  this.number = number;
 }

 public double reciprocal() {
   return 1/number.doubleValue();
 }

 public static void main(String[] args) {
   RestricExample<Integer> n1 = new RestricExample<Integer>(5);
   System.out.println("Reciprocal: " + n1.reciprocal());

   RestricExample<Double> n2 = new RestricExample<Double>(7.5);
   System.out.println("Reciprocal: " + n2.reciprocal());

   //error
   //RestricExample<String> s1 = new RestricExample<String>("Hello");
 }
}

Xây dựng một phương thức xử lý với nhiều kiểu dữ liệu đa dạng khác nhau.

Ví dụ tạo class tên MaximumTest trong package generic trong Java

package generic;
/**
 *
 * @author giasutinhoc.vn
 */
public class MaximumTest {
 // determines the largest of three Comparable objects
 public <T extends Comparable<T>> T maximum(T x, T y, T z) {
   T max = x; // assume x is initially the largest

   if (y.compareTo(max) > 0) {
     max = y; // y is the largest so far
   }

   if (z.compareTo(max) > 0) {
    max = z; // z is the largest now
   }

   return max; // returns the largest object
 }

 public static void main(String args[]) {
   // Create object
   MaximumTest mt = new MaximumTest();
   System.out.println("Max of 3, 4, 5 is " + mt.maximum(3, 4, 5));
   System.out.println("Maxm of 6.6, 8.8, 7.7 is " + mt.maximum(6.6, 8.8, 7.7));
   System.out.println("Max of pear, apple, orange is " + mt.maximum("pear", "apple", "orange"));
 }

Kết quả khi sau khi chạy như sau:

Max of 3, 4, 5 is 5
Max of 6.6, 8.8, 7.7 is 8.8
Max of pear, apple, orange is pear

Một số hạn chế của Generic

Generic sẽ có một số hạn chế như sau

Dữ liệu kiểu nguyên thủy không thể khởi tạo generic

Pair<int, char> p = new Pair<>(8, 'a'); //error
Pair<Integer, Character> p = new Pair<>(8, 'a');

Với kiểu dữ liệu không thể tạo instance

class Gen<T> {
 T obj;

 Gen() {
   obj= new T(); //Illegal (error)
 }
}

Không thể là static trong class

class Gen<T> {
 static T obj; //Kiểu T không thể là static
 static T getObj() { //Phương thức không thể static
   return obj;
 }
}

Không thể tạo được mảng – Generic trong java

Gen<Integer> gens[] = new Gen<Integer>[10]; //error
Gen<?> gens[] = new Gen<?>[10]; //ok
Gens[0] = new Gen<Integer>(25);
Gens[1] = new Gen<String>("Hello");

Không thể tạo class ngoại lệ là generic

Bài tập thực hành với generic

Bài thực hành thứ nhất

Tạo class tên MyArrayList rồi thực hiện các công việc sau:

  • Thêm một số nguyên 
  • Thêm một số thực
  • Thêm một giá trị boolean
  • Thêm một chuỗi
  • In ra màn hình 4 giá trị trên

Bài thực hành thứ hai

Tạo class tên MyGenericArrayList và thực hiện các công việc sau:

  • Tham số hoá dữ liệu về dạng nteger.
  • Sử dụng vòng lặp để nhập các số từ 1 đến 10 vào ArrayList.
  • In ra màn hình các giá trị vừa rồi

Kết luận

Các Generic trong Java là một tính năng quan trọng giúp tăng tính linh hoạt và tái sử dụng mã trong chương trình. 

Việc sử dụng Generics cho phép chúng ta tạo ra các lớp hoặc phương thức có thể áp dụng cho nhiều kiểu dữ liệu khác nhau mà không cần viết lại nhiều mã. Do đó, hãy học cách sử dụng Generic trong java thật chăm chỉ nhé!

Bài viết gốc được đăng tại: giasutinhoc.vn

Alert: You are not allowed to copy content or view source !!