Array Instance Variable สามารถ Initialize ได้ผ่าน Constructor หรือ Setter Method เหมือน Field ปกติ
วิธีที่ 1: ผ่าน Constructor (แนะนำ - Immutable Ready)
public class Student {
private String name;
private int age;
private String[] subjects; // Array Field
// Constructor รับ Array Parameter
public Student(String name, int age, String[] subjects) {
this.name = name;
this.age = age;
// Defensive Copy: ป้องกัน External Modification
this.subjects = subjects.clone(); // หรือ Arrays.copyOf(subjects, subjects.length)
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.print("Subjects: ");
for (String s : subjects) System.out.print(s + " ");
System.out.println();
}
public static void main(String[] args) {
String[] subs = {"Mathematics", "English", "Science", "Social"};
Student student = new Student("Krishna", 25, subs);
student.display();
// แก้ไข Array ต้นทาง ไม่ส่งผลต่อ Object (เพราะ Clone)
subs[0] = "Hacked";
student.display(); // ยังคงเป็น Mathematics
}
}
ผลลัพธ์
Name: Krishna Age: 25 Subjects: Mathematics English Science Social Name: Krishna Age: 25 Subjects: Mathematics English Science Social
วิธีที่ 2: ผ่าน Setter Method (Mutable)
public class Student {
private String name;
private int age;
private String[] subjects;
public void setName(String name) { this.name = name; }
public void setAge(int age) { this.age = age; }
// Setter สำหรับ Array
public void setSubjects(String[] subjects) {
this.subjects = subjects != null ? subjects.clone() : new String[0];
}
public void display() { ... }
public static void main(String[] args) {
Student student = new Student();
student.setName("Krishna");
student.setAge(25);
student.setSubjects(new String[]{"Math", "English", "Science"});
student.display();
}
}
Best Practices สำหรับ Array Field
| Practice | เหตุผล |
|---|---|
| Defensive Copy ใน Constructor/Setter | ป้องกัน Caller แก้ไข Array ต้นทางส่งผลต่อ Object |
| Getter คืน Copy/Unmodifiable View | ป้องกัน Caller แก้ไข Internal State |
| ใช้ List/Collection แทน Array | Flexible, Rich API, รองรับ Generics ดีกว่า |
| ทำ Field เป็น final (ถ้าไม่ Setter) | Immutable Reference (แต่ Array Content ยัง Mutate ได้) |
Getter ที่ปลอดภัย
// Option 1: Return Copy
public String[] getSubjects() {
return subjects.clone();
}
// Option 2: Return Unmodifiable List (Java 10+)
public List<String> getSubjects() {
return List.of(subjects); // Immutable Copy
}
// Option 3: Return Stream (ไม่ Expose Array)
public Stream<String> subjectsStream() {
return Arrays.stream(subjects);
}
สรุป
- Initialize Array Field ผ่าน Constructor (Immutable Style) หรือ Setter (Mutable Style)
- Always Defensive Copy (clone/copyOf) ใน Constructor และ Setter
- Getter ควรคืน Copy หรือ View ไม่คืน Array Reference ตรงๆ
- พิจารณาใช้
List<String>แทนString[]สำหรับ Design ที่ดีกว่า