polymorphism หมายถึงการมีได้หลายรูปแบบ ในภาษาจาวาตัวอย่างของการมีได้หลายรูปแบบ เช่น เมธอดที่รองรับชนิดของข้อมูลที่แตกต่างกันได้ เช่น เมธอด println() หรือการสร้างออบเจกต์ด้วยพารามิเตอร์ที่แตกต่างกัน เป็นต้น

ในทางทฤษฎี polymorphism แบ่งออกเป็น Ad-hoc polymorphism, Subtype polymorphism และ Parametric polymorphism

Ad-hoc polymorphism หมายถึง ฟังก์ชันที่สามารถนำไปใช้กับอาร์กิวเมนต์ประเภทต่างๆ ได้ แต่จะมีพฤติกรรมแตกต่างกันไปตามประเภทของอาร์กิวเมนต์ที่ใช้ สำหรับในภาษาจาวาคือการทำเมธอดโอเวอร์โหลด

Subtype polymorphism หมายถึง การใช้อินสแตนซ์ของคลาสย่อย (sub-class) เมื่อมีการอนุญาตในอินสแตนซ์ของคลาสพื้นฐาน (base-class) หรือให้เข้าใจง่ายๆคือ ในภาษาจาวาจะเป็นการสร้างออบเจกต์โดยกำหนดชนิดของตัวแปรเป็น base-classs แต่สร้างออบเจกต์ด้วย sub class เช่น เรามี base-class เป็นคลาส Account และมี sub-class เป็นคลาส SavingAccount ดังนั้นการใช้ subtype polymorphism จะเป็นดังตัวอย่างด้านล่าง

Account variable = new SavingAccount();

Parametric polymorphism หมายถึงการเขียนโปรแกรมโดยไม่ระบุชนิดของข้อมูลและโปรแกรมสามารถใช้ได้กับทุกชนิดของข้อมูล สำหรับในภาษาจาวาคือความสามารถที่เรียกว่า generics

ในมุมมองของภาษาจาวามี polymorphism สองแบบคือ แบบ static (เวลาคอมไพล์) ทำได้โดยวิธีการโอเวอร์โหลด และแบบ dynamic (รันไทม์) ทำได้โดยการสืบทอดคลาสและโอเวอร์ไรด์เมธอด ตัวอย่างดานล่างเป็นตัวอย่างแบบ dynamic ซึ่งในการใช้งานโปรแกรม เมธอด getFileInfo() ในคลาส ImageFile จะถูกเรียกใช้งานเพราะว่าออบเจกต์ถูกสร้างโดยการอ้างอิง sub-class แม้ว่าตัวแปรจะอ้างอิง base-class ก็ตาม

class File {

    protected String fullName;

    // constructor with a single parameter

    // getters and setters

    public void printFileInfo() {
        String info = this.getFileInfo(); // here is polymorphic behavior!!!
        System.out.println(info);
    }

    protected String getFileInfo() {
        return “File: ” + fullName;
    }
}

class ImageFile extends File {

    protected int width;
    protected int height;
    protected byte[] content;

    // constructor

    // getters and setters

    @Override
    protected String getFileInfo() {
        return String.format(“Image: %s, width: %d, height: %d”, fullName, width, height); 
    }
}

===================================================

File img = new ImageFile(“/path/to/file/img.png”, 480, 640, someBytes); // สร้างอออบเจกต์โดยตัวแปรกำหนดชนิดของข้อมูลเป็น base-class แต่สร้างออบเจกต์จาก sub-class

img.printFileInfo(); // It prints “Image: /path/to/file/img.png, width: 480, height: 640” เมื่อมีการใช้งาน เมธอด getFileInfo() ในคลาส ImageFile จะถูกเรียกใช้งานเพราะว่าออบเจกต์ถูกสร้างโดยการอ้างอิง sub-class