บทนำ: ปัญหาของการ Initialize ข้อมูล
จนถึงตอนนี้ เราสร้าง object แล้ว attributes ยังว่างเปล่า
java// ❌ ปัญหา: Object สร้างเสร็จแต่ยังไม่มี data
public class Student {
private String name;
private double gpa;
private int year;
}
// สร้าง object
Student student = new Student();
// ต้อง set ค่าเอง (จำเบื่อ + ลืมได้)
student.setName("John");
student.setGPA(3.75);
student.setYear(2);
// ❌ ถ้า forget ชุมพล ข้อมูลจะ invalid
Student incomplete = new Student();
// incomplete.name = null, gpa = 0, year = 0 (default values)
ปัญหา:
- ❌ ต้อง set ค่าหลายครั้ง
- ❌ ลืมได้ → object invalid
- ❌ Code ยาว + error-prone
ยาวไปอยากเลือกอ่าน
- บทนำ: ปัญหาของการ Initialize ข้อมูล
- Constructor คืออะไร?
- Syntax: การเขียน Constructor
- ตัวอย่างที่ 1: Constructor พื้นฐาน
- Constructor ด้วย Validation
- ตัวอย่างที่ 2: Constructor ที่ตรวจสอบข้อมูล
- Constructor vs Setter
- ความต่างกัน
- ตัวอย่างที่ 3: Constructor vs Setter
- Constructor ด้วยการ Assign Complex Objects
- ตัวอย่างที่ 4: Initialize Collections
- Constructor ที่เรียก Helper Methods
- ตัวอย่างที่ 5: Constructor เรียก Private Methods
- Object Initialization Sequence
- ลำดับการทำงาน
- ตัวอย่างที่ 6: ดูการ Initialize
- Constructor ด้วย Default Values
- ตัวอย่างที่ 7: Constructor กับ Default Values
- Best Practices: Constructor Design
- 1. Validate ทุกค่าที่ input
- 2. Initialize ALL attributes
- 3. Keep it Simple
- 4. Call Setters ใน Constructor
- ตัวอย่างสุดท้าย: Complete Class ด้วย Constructor
- สรุป: Constructor
Constructor คืออะไร?
Constructor = method พิเศษที่เรียกอัตโนมัติ เมื่อสร้าง object
textConstructor มีลักษณะพิเศษ:
1. ชื่อเหมือน class name
2. ไม่มี return type (ไม่ใช่ void)
3. ถูกเรียกโดยอัตโนมัติตอน new
4. ใช้ initialize data
Syntax: การเขียน Constructor
java[access modifier] ClassName(parameters) {
// initialize code
}
ตัวอย่าง:
public Student(String name, double gpa, int year) {
this.name = name;
this.gpa = gpa;
this.year = year;
}
ตัวอย่างที่ 1: Constructor พื้นฐาน
javapublic class Student {
private String name;
private double gpa;
private int year;
// Constructor
public Student(String name, double gpa, int year) {
this.name = name;
this.gpa = gpa;
this.year = year;
}
public void displayInfo() {
System.out.printf("Name: %s | GPA: %.2f | Year: %d\n",
name, gpa, year);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
// ✓ Constructor ทำให้ data initialize เลย
Student student = new Student("John", 3.75, 2);
student.displayInfo(); // Name: John | GPA: 3.75 | Year: 2
}
}
ข้อดี:
- ✓ Object สร้างเสร็จ data พร้อม
- ✓ ไม่ต้อง set ค่าแยก
- ✓ ไม่ลืม initialize
Constructor ด้วย Validation
ตัวอย่างที่ 2: Constructor ที่ตรวจสอบข้อมูล
javapublic class BankAccount {
private String accountNumber;
private String accountHolder;
private double balance;
// Constructor ที่มี validation
public BankAccount(String accountNumber, String accountHolder, double initialBalance) {
// Validation 1: accountNumber
if (accountNumber == null || accountNumber.isEmpty()) {
throw new IllegalArgumentException("Account number cannot be empty");
}
// Validation 2: accountHolder
if (accountHolder == null || accountHolder.isEmpty()) {
throw new IllegalArgumentException("Account holder cannot be empty");
}
// Validation 3: initialBalance
if (initialBalance < 0) {
throw new IllegalArgumentException("Initial balance cannot be negative");
}
// Initialize (หลังผ่าน validation ทั้งหมด)
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.balance = initialBalance;
}
public void displayInfo() {
System.out.printf("Account: %s | Holder: %s | Balance: %.2f\n",
accountNumber, accountHolder, balance);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
System.out.println("=== Valid Account ===");
BankAccount account = new BankAccount("ACC001", "John Doe", 50000);
account.displayInfo();
System.out.println("\n=== Invalid Account (negative balance) ===");
try {
BankAccount invalid = new BankAccount("ACC002", "Jane", -5000);
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("\n=== Invalid Account (empty holder) ===");
try {
BankAccount invalid = new BankAccount("ACC003", "", 50000);
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output:
text=== Valid Account ===
Account: ACC001 | Holder: John Doe | Balance: 50000.00
=== Invalid Account (negative balance) ===
Error: Initial balance cannot be negative
=== Invalid Account (empty holder) ===
Error: Account holder cannot be empty
Constructor vs Setter
ความต่างกัน
text┌──────────────────┬──────────────────┬──────────────────┐
│ │ Constructor │ Setter │
├──────────────────┼──────────────────┼──────────────────┤
│ เรียกเมื่อ │ new object │ โปรแกรม call │
│ ที่มา │ initialization │ change value │
│ บังคับ │ ต้องใช้ │ optional │
│ ใช้ │ วัน initialize │ วัน update │
└──────────────────┴──────────────────┴──────────────────┘
ตัวอย่างที่ 3: Constructor vs Setter
javapublic class Product {
private String productID;
private String productName;
private double price;
private int quantity;
// Constructor: initialize ครั้งแรก
public Product(String id, String name, double price, int qty) {
setProductID(id);
setProductName(name);
setPrice(price);
setQuantity(qty);
}
// Setter: update ภายหลัง
public void setProductID(String id) {
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("Product ID cannot be empty");
}
this.productID = id;
}
public void setProductName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Product name cannot be empty");
}
this.productName = name;
}
public void setPrice(double price) {
if (price < 0) {
throw new IllegalArgumentException("Price cannot be negative");
}
this.price = price;
}
public void setQuantity(int qty) {
if (qty < 0) {
throw new IllegalArgumentException("Quantity cannot be negative");
}
this.quantity = qty;
}
public void displayInfo() {
System.out.printf("ID: %s | Name: %s | Price: %.2f | Qty: %d\n",
productID, productName, price, quantity);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
// Constructor: ให้ค่าเมื่อ initialize
Product laptop = new Product("P001", "Laptop", 25000, 10);
laptop.displayInfo();
// Setter: update ภายหลัง
laptop.setPrice(24000); // ลดราคา
laptop.setQuantity(15); // เพิ่มสต็อก
laptop.displayInfo();
}
}
Constructor ด้วยการ Assign Complex Objects
ตัวอย่างที่ 4: Initialize Collections
javaimport java.util.ArrayList;
import java.util.List;
public class Course {
private String courseID;
private String courseName;
private List<String> studentList; // Collection
// Constructor ที่ initialize collection
public Course(String id, String name) {
this.courseID = id;
this.courseName = name;
this.studentList = new ArrayList<>(); // ✓ Initialize empty list
}
// Business methods
public void addStudent(String studentName) {
if (studentName == null || studentName.isEmpty()) {
throw new IllegalArgumentException("Student name cannot be empty");
}
this.studentList.add(studentName);
System.out.println("✓ Added: " + studentName);
}
public void displayStudents() {
System.out.printf("Course: %s | Students: %s\n", courseName, studentList);
}
public int getStudentCount() {
return studentList.size();
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
// Constructor initialize empty list
Course course = new Course("CS101", "Object-Oriented Programming");
course.addStudent("John");
course.addStudent("Jane");
course.addStudent("Bob");
course.displayStudents();
System.out.println("Total: " + course.getStudentCount());
}
}
Output:
text✓ Added: John
✓ Added: Jane
✓ Added: Bob
Course: Object-Oriented Programming | Students: [John, Jane, Bob]
Total: 3
Constructor ที่เรียก Helper Methods
ตัวอย่างที่ 5: Constructor เรียก Private Methods
javapublic class Configuration {
private String databaseURL;
private int portNumber;
private String logLevel;
private boolean isInitialized;
// Constructor
public Configuration(String dbURL, int port, String logLevel) {
setDatabaseURL(dbURL); // เรียก setter (ที่มี validation)
setPortNumber(port);
setLogLevel(logLevel);
initializeSystem(); // เรียก helper method
}
// Setter (with validation)
private void setDatabaseURL(String url) {
if (url == null || !url.startsWith("jdbc:")) {
throw new IllegalArgumentException("Invalid database URL");
}
this.databaseURL = url;
}
private void setPortNumber(int port) {
if (port < 1000 || port > 9999) {
throw new IllegalArgumentException("Port must be between 1000-9999");
}
this.portNumber = port;
}
private void setLogLevel(String level) {
if (!level.matches("DEBUG|INFO|WARN|ERROR")) {
throw new IllegalArgumentException("Invalid log level");
}
this.logLevel = level;
}
// Helper method - called from constructor
private void initializeSystem() {
System.out.println("[System Init] Connecting to: " + databaseURL);
System.out.println("[System Init] Port: " + portNumber);
System.out.println("[System Init] Log level: " + logLevel);
this.isInitialized = true;
System.out.println("[System Init] ✓ System initialized");
}
public void displayConfig() {
System.out.printf("DB: %s | Port: %d | Log: %s\n",
databaseURL, portNumber, logLevel);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
System.out.println("=== Creating Configuration ===");
Configuration config = new Configuration("jdbc:mysql://localhost", 3306, "INFO");
System.out.println("\n=== Config Details ===");
config.displayConfig();
}
}
Output:
text=== Creating Configuration ===
[System Init] Connecting to: jdbc:mysql://localhost
[System Init] Port: 3306
[System Init] Log level: INFO
[System Init] ✓ System initialized
=== Config Details ===
DB: jdbc:mysql://localhost | Port: 3306 | Log: INFO
Object Initialization Sequence
ลำดับการทำงาน
text1. new Student()
↓
2. Allocate memory ใน Heap
↓
3. Initialize attributes ด้วยค่า default
(String = null, int = 0, double = 0.0, boolean = false)
↓
4. Constructor code ทำงาน
↓
5. Object ready to use
ตัวอย่างที่ 6: ดูการ Initialize
javapublic class InitializationOrder {
private String name; // default = null
private int age; // default = 0
private double gpa; // default = 0.0
private boolean isActive; // default = false
public InitializationOrder(String name, int age) {
System.out.println("Constructor started");
System.out.println("Before assignment - name: " + this.name);
System.out.println("Before assignment - age: " + this.age);
this.name = name;
this.age = age;
System.out.println("After assignment - name: " + this.name);
System.out.println("After assignment - age: " + this.age);
}
public void displayInfo() {
System.out.printf("Name: %s | Age: %d | GPA: %.2f | Active: %s\n",
name, age, gpa, isActive);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
System.out.println("=== Creating Object ===\n");
InitializationOrder obj = new InitializationOrder("John", 25);
System.out.println("\n=== Display Info ===");
obj.displayInfo();
}
}
Output:
text=== Creating Object ===
Constructor started
Before assignment - name: null
Before assignment - age: 0
After assignment - name: John
After assignment - age: 25
=== Display Info ===
Name: John | Age: 25 | GPA: 0.00 | Active: false
Constructor ด้วย Default Values
ตัวอย่างที่ 7: Constructor กับ Default Values
javapublic class User {
private String username;
private String password;
private int accountStatus; // 0=new, 1=active, 2=suspended
private long createdTime;
private int loginCount;
public User(String username, String password) {
this.username = username;
this.password = password;
this.accountStatus = 0; // NEW account
this.createdTime = System.currentTimeMillis();
this.loginCount = 0; // No login yet
System.out.println("✓ New user created: " + username);
}
public void login() {
this.accountStatus = 1; // Mark as active
this.loginCount++;
}
public void displayInfo() {
System.out.printf("User: %s | Status: %d | Logins: %d | Created: %d\n",
username, accountStatus, loginCount, createdTime);
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
// Constructor ตั้ง default values
User user = new User("john_doe", "password123");
user.displayInfo();
System.out.println("\n=== After Login ===");
user.login();
user.displayInfo();
}
}
Best Practices: Constructor Design
1. Validate ทุกค่าที่ input
java// ✓ ดี
public Student(String id, String name, double gpa) {
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("ID cannot be empty");
}
if (gpa < 0 || gpa > 4.0) {
throw new IllegalArgumentException("GPA must be 0-4.0");
}
this.id = id;
this.name = name;
this.gpa = gpa;
}
// ❌ ไม่ดี
public Student(String id, String name, double gpa) {
this.id = id; // No validation
this.name = name;
this.gpa = gpa;
}
2. Initialize ALL attributes
java// ✓ ดี
public class Order {
private String orderID;
private double totalAmount;
private List<Item> items;
private long createdTime;
public Order(String id) {
this.orderID = id;
this.totalAmount = 0;
this.items = new ArrayList<>(); // ✓ Initialize
this.createdTime = System.currentTimeMillis();
}
}
// ❌ ไม่ดี
public class Order {
private String orderID;
private double totalAmount;
private List<Item> items;
public Order(String id) {
this.orderID = id;
// totalAmount not initialized
// items = null (NullPointerException later!)
}
}
3. Keep it Simple
java// ✓ ดี: Constructor ง่ายๆ
public class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
// ⚠️ ไม่ดี: Constructor ยุ่งเหยิง
public class Point {
private double x;
private double y;
public Point(double x, double y) {
// Business logic ยุ่งๆ
loadConfigFile();
connectToDatabase();
calculateDistances();
// ...
}
}
4. Call Setters ใน Constructor
java// ✓ ดี: ใช้ setter ให้ reuse validation
public class Account {
private double balance;
public Account(double initialBalance) {
setBalance(initialBalance); // ← ใช้ setter
}
public void setBalance(double balance) {
if (balance < 0) {
throw new IllegalArgumentException("Cannot be negative");
}
this.balance = balance;
}
}
// ❌ ไม่ดี: validation code ซ้ำ
public class Account {
private double balance;
public Account(double initialBalance) {
if (initialBalance < 0) { // ← ซ้ำกับใน setter
throw new IllegalArgumentException("Cannot be negative");
}
this.balance = initialBalance;
}
public void setBalance(double balance) {
if (balance < 0) { // ← ซ้ำ
throw new IllegalArgumentException("Cannot be negative");
}
this.balance = balance;
}
}
ตัวอย่างสุดท้าย: Complete Class ด้วย Constructor
javapublic class Employee {
private String employeeID;
private String name;
private String department;
private double salary;
private int startYear;
// Constructor
public Employee(String id, String name, String dept, double salary, int year) {
// Validation
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("Employee ID required");
}
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name required");
}
if (salary < 0) {
throw new IllegalArgumentException("Salary cannot be negative");
}
if (year < 2000 || year > 2025) {
throw new IllegalArgumentException("Invalid start year");
}
// Assignment
this.employeeID = id;
this.name = name;
this.department = dept;
this.salary = salary;
this.startYear = year;
// Log
System.out.printf("✓ Employee created: %s (%s)\n", name, id);
}
// Business methods
public void giveSalaryIncrease(double percentage) {
if (percentage < 0 || percentage > 50) {
throw new IllegalArgumentException("Invalid percentage");
}
double increment = this.salary * percentage / 100;
this.salary += increment;
System.out.printf("✓ Salary increased by %.1f%% to %.2f\n",
percentage, this.salary);
}
public int getYearsOfService() {
return 2025 - this.startYear;
}
public void displayInfo() {
System.out.printf("ID: %s | Name: %s | Dept: %s | Salary: %.2f | Years: %d\n",
employeeID, name, department, salary, getYearsOfService());
}
}
// ใช้งาน
public class Main {
public static void main(String[] args) {
System.out.println("=== Creating Employees ===");
Employee emp1 = new Employee("E001", "John Smith", "Engineering", 50000, 2020);
Employee emp2 = new Employee("E002", "Jane Doe", "Marketing", 45000, 2022);
System.out.println("\n=== Employee Details ===");
emp1.displayInfo();
emp2.displayInfo();
System.out.println("\n=== Salary Increase ===");
emp1.giveSalaryIncrease(10);
emp1.displayInfo();
System.out.println("\n=== Invalid Creation Attempt ===");
try {
Employee invalid = new Employee("E003", "", "HR", -5000, 2025);
} catch (IllegalArgumentException e) {
System.out.println("❌ Error: " + e.getMessage());
}
}
}
Output:
text=== Creating Employees ===
✓ Employee created: John Smith (E001)
✓ Employee created: Jane Doe (E002)
=== Employee Details ===
ID: E001 | Name: John Smith | Dept: Engineering | Salary: 50000.00 | Years: 5
ID: E002 | Name: Jane Doe | Dept: Marketing | Salary: 45000.00 | Years: 3
=== Salary Increase ===
✓ Salary increased by 10.0% to 55000.00
ID: E001 | Name: John Smith | Dept: Engineering | Salary: 55000.00 | Years: 5
=== Invalid Creation Attempt ===
❌ Error: Name required
สรุป: Constructor
text┌──────────────────────────────────────────────┐
│ Constructor: การกำหนดค่าเริ่มต้น │
├──────────────────────────────────────────────┤
│ │
│ ✓ Constructor คืออะไร │
│ └─ Method พิเศษเรียกอัตโนมัติตอน new │
│ │
│ ✓ ใช้ทำอะไร │
│ ├─ Initialize attributes │
│ ├─ Validate input values │
│ ├─ Initialize collections │
│ └─ Setup system │
│ │
│ ✓ Best Practices │
│ ├─ Validate ทุกค่า │
│ ├─ Initialize ALL attributes │
│ ├─ Keep constructor simple │
│ ├─ Call setters (reuse validation) │
│ └─ Handle errors gracefully │
│ │
│ ✓ ประโยชน์ │
│ ├─ Object ready ตั้งแต่เริ่ม │
│ ├─ Ensure valid state │
│ ├─ Reduce boilerplate code │
│ └─ Prevent bugs │
│ │
└──────────────────────────────────────────────┘
