2012-03-19 43 views
7

Để thực hiện một lớp học bất biến gì tôi có thể làm là:thực hiện một lớp học bất biến trong java

1) Làm cho lớp thức
2) không cung cấp setters
3) đánh dấu tất cả các biến như thức

Nhưng nếu lớp học của tôi có một đối tượng của một số lớp khác thì, ai đó có thể thay đổi giá trị của đối tượng đó

class MyClass{ 
final int a; 
final OtherClass other 

MyClass(int a ,OtherClass other){ 
    this.a = a; 
    this.other = other; 
} 

int getA(){ 
    return a; 
} 

OtherClass getOther(){ 
    return other; 
} 

public static void main(String ags[]){ 
    MyClass m = new Myclass(1,new OtherClass); 
    Other o = m.getOther(); 
    o.setSomething(xyz) ; //This is the problem ,How to prevent this? 

} 
} 
+4

không viết phương pháp đã đặt –

+0

@LuiggiMendoza, tôi nghĩ rằng Other/OtherClass có nghĩa là trở thành lớp mà anh ấy không kiểm soát. –

+3

Viết trình bao bọc cho lớp khác và chỉ làm cho getters. – Nican

Trả lời

3

A) Tận dụng tối OtherClass bất biến cũng

hoặc

B) Không cho phép truy cập trực tiếp đến đối tượng OtherClass, thay vì chỉ cung cấp thu khí để hoạt động như một proxy.

Chỉnh sửa để thêm: Bạn thể tạo một bản sao sâu sắc về OtherClass và trả về một bản sao chứ không phải là bản gốc, nhưng điều đó thường không phải là loại hành vi bạn mong đợi ở Java.

1

Tôi giả định OtherClass (theo cách bạn nói Khác một lần) có nghĩa là lớp bạn không kiểm soát hoặc phải có setter.

Nếu bạn không thể xóa getOther, hãy đổi thành getOtherView và trả lại chế độ chỉ đọc other. Sẽ có các trình bao bọc cho tất cả các phương thức get, nhưng không có các phương thức được thiết lập.

1

Trả lại các dòng vô tính sâu từ getters của bạn. Bạn có thể thấy điều này không phải là nhiệm vụ dễ dàng.

1

Tất cả các đối tượng được tham chiếu trong lớp bất biến nên không thay đổi, hoặc ít nhất được đóng gói riêng tư và đảm bảo rằng chúng không bị sửa đổi (không phải bên trong các phương thức lớp học của bạn và chắc chắn không phải từ bên ngoài). Ví dụ, nếu bạn có tình trạng này:

public class MyImmutable { 
    private MutableClass mutableObject; 
} 

... Bạn có thể không cung cấp phương pháp getMutableObject(), bởi vì làm như vậy sẽ mở ra cánh cửa cho những thay đổi bên ngoài, như thế này:

myImmutable.getMutableObject().setSomeAttribute(newValue); 

Là một trường hợp đặc biệt ở trên, tất cả các bộ sưu tập và/hoặc bản đồ phải được thực hiện bất biến, với các phương thức ummodifiableXXX() trong lớp Collections.

1

bạn không thể (hợp lý) dừng điều đó trong java. nếu bạn không có quyền kiểm soát lớp khác, có nhiều cách để có được hành vi bất biến, nhưng nó có thể rất tốn kém trong thực tế. về cơ bản, bạn phải luôn luôn trả về một bản sao của lớp đó trong bất kỳ giá trị trả về phương thức công khai nào. (jdk thực sự có vấn đề này với lớp TimeZone).

1

Nhưng nếu lớp học của tôi có một đối tượng của một số lớp khác sau đó, somone có thể thay đổi giá trị của đối tượng đó ...

đối tượng Java không nguyên thủy. Nếu bạn đánh dấu một nguyên thủy là cuối cùng, thì giá trị của nó không thể thay đổi khi nó được gán. Tuy nhiên, nội dung đối tượng không thể là cuối cùng, chỉ các tham chiếu đối tượng mới có thể là cuối cùng. Vì vậy, bạn không thể làm cho một đối tượng theo cách này.

Một giải pháp có thể từ bỏ tất cả các phương thức setter/mutator có thể thay đổi các trường cụ thể của đối tượng và đóng gói chúng theo cách bạn chỉ có thể truy cập chúng chứ không thay đổi chúng.

2

Tính không thay đổi được xem là tốt nhất từ ​​quan điểm của người dùng API. Vì vậy, API đối tượng của bạn cần phải đáp ứng hai điều kiện sau:

  1. Không có cách nào cho người dùng bên ngoài để thay đổi giá trị của đối tượng
  2. Một sự đảm bảo rằng bất cứ lúc nào đọc sử dụng hoặc sử dụng các giá trị của đối tượng trong tương lai, nó sẽ nhận được kết quả tương tự

Lưu ý quan trọng: đó là trong thực tế OK để có dữ liệu có thể thay đổi bên trong một đối tượng bất biến miễn là nó cư xử như một đối tượng bất biến từ quan điểm của người sử dụng API. Hãy xem xét java.lang.String ví dụ: mặc dù nó thường được coi là lớp không thể thay đổi dứt khoát, nó thực tế có một trường nội bộ có thể thay đổi để lưu bộ nhớ đệm hashCode (không nhiều người biết điều này!).

Vì vậy, để giải quyết câu hỏi của bạn, nếu bạn muốn chứa khác (có thể thay đổi) đối tượng bên trong một đối tượng bất biến sau đó bạn thường cần phải làm một hoặc nhiều điều sau đây:

  • Đảm bảo rằng không ai khác có thể thay đổi giá trị của đối tượng có thể thay đổi. Thông thường điều này có nghĩa là đảm bảo rằng không ai khác có thể có tham chiếu đến đối tượng có thể thay đổi được, do đó, điều này thường chỉ có thể nếu bạn tự tạo đối tượng thay vì chấp nhận tham chiếu từ bên ngoài.
  • Lấy một bản sao sâu phòng thủ của đối tượng có thể thay đổi và không đưa ra các tham chiếu đến bản sao mới. Chỉ cho phép các hoạt động đọc bản sao mới trong API công khai. Nếu bạn cần phải đưa ra một tham chiếu đến đối tượng này, sau đó bạn cần phải có một bản sao phòng thủ (để tránh đưa ra một tham chiếu đến bản sao nội bộ).
  • Sử dụng trình bao bọc không thay đổi cho đối tượng có thể thay đổi. Một cái gì đó như Collections.unmodifiableList. Điều này rất hữu ích nếu bạn muốn đưa ra một tham chiếu đến đối tượng có thể thay đổi bên trong nhưng không muốn chạy nguy cơ bị sửa đổi.

Tất cả các giải pháp này hơi khó hiểu - một giải pháp tốt hơn tổng thể là tránh sử dụng các đối tượng có thể thay đổi trong các đối tượng bất biến. Về lâu dài nó yêu cầu rắc rối vì sớm hay muộn một tham chiếu có thể thay đổi sẽ bị rò rỉ và bạn sẽ gặp phải một lỗi rất khó tìm. Bạn đang di chuyển tốt hơn hướng tới một hệ thống phân cấp đầy đủ các đối tượng bất biến (phương pháp của ngôn ngữ như Scala và Clojure)

+0

Hầu như bất kỳ đối tượng nào có chứa bộ sưu tập có kích thước biến sẽ có mảng như một cửa hàng sao lưu, vì vậy tránh hoàn toàn các đối tượng có thể thay đổi được nói chung là không thực tế (mọi thứ có thể được thực hiện với một mảng có thể được thực hiện bằng cây không thay đổi) nhưng trong nhiều trường hợp mảng sẽ có nhiều hơn một bậc độ lớn nhanh hơn). – supercat

1

Có thể tạo ra các lớp học bất biến trong java bằng cách sau

1.Don't Cung cấp setter phương pháp.

2.Thực hiện tất cả các trường là cuối cùng và riêng tư.

3.Thực hiện lớp học cuối cùng.

+0

chỉ hợp lệ khi các trường không thay đổi. – KillBill

Các vấn đề liên quan