ลองดูตัวอย่างการสร้างตัวแปรของคลาสที่เป็นแบบ int และการ set กับ get ตามปกติกันก่อน
public class MyClass{ private int value; public void set(int v){ value = v; } public int get(){ return value; } public static void main(String[] args){ MyClass m = new MyClass(); m.set(5); System.out.println(m.get()); } }
คราวนี้ ถ้าเราต้องการส่งค่าที่ไม่ใช่ตัวเลข เช่น m.set("Hello"); ไป สิ่งที่เกิดขึ้นก็คือ compile ไม่ผ่าน เพราะชนิดของข้อมูลที่ส่งไป กับชนิดของข้อมูลที่เอาไปรับไม่ตรงกัน ก็จำเป็นจะต้องเขียน method ใหม่ แถมยังไม่พอ ต้องประกาศตัวแปรของคลาสใหม่เพื่อมารับข้อมูลชนิดนี้ด้วย
เพื่อที่จะลดความซับซ้อนตรงนี้ลง (แต่ไปเพิ่มความงงให้กับการเขียนโปรแกรม) ลองใช้ Generic class กันดูตามนี้ครับ
public class MyClass<T>{ private T value; public void set(T v){ value = v; } public T get(){ return value; } public static void main(String[] args){ //MyClass m = new MyClass(); MyClass<Integer> m1 = new MyClass<Integer>(); //m.set(10); m1.set(new Integer(10)); System.out.println(m1.get()); MyClass<String> m2 = new MyClass<String>(); m2.set(new String("Hello")); System.out.println(m2.get()); } }
ผลลัพธ์ที่ได้คือ
10
Hello
ซึ่งจะสังเกตเห็นว่า เราก็ยังมีคลาสเดียว แต่ตอนสร้าง Object เราสร้างมันสองตัวคือ m1 เป็นแบบ Integer และ m2 เป็นแบบ String แต่ทั้งสอง Object ก็ใช้ตัวแปรคลาสและ method ร่วมกันได้
ข้อสังเกต
- เราสร้างคลาสด้วย public class MyClass<T> ซึ่งหลังคลาสจะตามด้วย Generic type ที่ระบุด้วยเครื่องหมาย <T> และตัว T ก็เป็นชื่อชนิด (จะตั้งเป็นตัวอื่นก็ได้ แต่มักใช้ T แทน Type)
- จากนั้นเราก็ใช้ T เหมือนชนิดของตัวแปรทั่วไป เช่น private T value; ก็คือการกำหนดให้ตัวแปร value เป็นชนิด T ซึ่งจะกลายเป็น reference type เช่น Integer, Double, String ในอนาคตได้
- ในส่วนของ main() เวลาสร้าง Object ต้องระบุชนิดตามหลังคลาสด้วย (สังเกตว่าสัญลักษณ์
ตามติดหลังชื่อคลาสตลอด) เช่น MyClass<Integer> m1 = new MyClass<Integer>(); ซึ่งในจาวารุ่น 7.0 ไป เราสามารถลดรูปให้เหลือแค่ MyClass<Integer> m1 = new MyClass<>(); ได้ - เวลาส่งค่าให้ method ของ Generic class ในกรณีนี้ เราก็ไม่สามารถส่งค่าตัวแปรแบบทั่วไปได้ ต้องส่งเป็น Object ของคลาสไป เช่น m1.set(new Integer(10)); แทน