2013-05-21 54 views
18

This is a sentence từ Java Concurrency in PracticeKhác nhau giữa các đối tượng bất biến và hiệu quả không thay đổi?

Shared read-only đối tượng bao gồm bất biến và có hiệu quả bất biến đối tượng.

Sự khác biệt giữa các đối tượng không thay đổi và hiệu quả là gì?

+0

Xem [Làm các đối tượng không thay đổi có hiệu quả] (http://stackoverflow.com/questions/8707426/do-effectively-immutable-objects-make-sense) cũng đề cập đến cuốn sách mà bạn giới thiệu. – Bobulous

+0

Xem thêm [Phải tất cả các thuộc tính của một đối tượng bất biến là cuối cùng?] (Http://stackoverflow.com/questions/16061030/must-all-properties-of-an-immutable-object-be-final) – assylias

Trả lời

14

Thể hiện của một lớp học mà không phải là mở rộng và có các trường là tất cả final và bản thân không thay đổi là không thay đổi.

Các trường hợp của một lớp có trường không thể bị đột biến vì chi tiết về các phương thức của nó không thể thay đổi một cách hiệu quả. Ví dụ:

final class C { 
    final boolean canChange; 
    private int x; 
    C(boolean canChange) { this.canChange = canChange; } 
    public void setX(int newX) { 
    if (canChange) { 
     this.x = newX; 
    } else { 
     throw new IllegalStateException(); 
    } 
    } 
} 

Một số trường hợp C có hiệu quả bất biến và một số thì không thay đổi.

Ví dụ khác là mảng có độ dài bằng không.Chúng có hiệu quả bất biến mặc dù lớp có chứa chúng không thể thay đổi được vì không có phần tử nào trong chúng có thể thay đổi được.


Joe-E sử dụng trình xác minh để chứng minh rằng một số lớp chỉ cho phép các trường hợp bất biến. Bất cứ điều gì được đánh dấu bằng giao diện điểm đánh dấu Immutable đều được kiểm tra và một số lớp như String (có thể thay đổi một cách hiệu quả kể từ khi char[] không thoát ra) được ông cố làm không thay đổi.

Joe-E: A Security-Oriented Subset of Java nói

Giao diện Immutable, de được xác định bởi các thư viện Joe-E, được xử lý đặc biệt bằng ngôn ngữ: Joe-E veri fi er kiểm tra rằng mỗi đối tượng thực hiện giao diện này sẽ được (sâu) bất biến và tăng lỗi biên dịch nếu điều này không thể tự động được xác minh.

+0

"Các trường hợp của một lớp có các trường không thể bị đột biến vì các chi tiết của các phương thức của nó có thể thay đổi một cách hiệu quả" - đây là điều không thể tránh khỏi. _Effectively Immutable_ có thể là bất kỳ đối tượng nào miễn là nó không bị biến đổi sau khi nó được _safley publushed_ (ví dụ như thông qua tham chiếu dễ bay hơi) –

+0

@OpDeCirkel, Hậu tố có thể "không thay đổi" làm cho ý nghĩa "không có khả năng thay đổi" không chỉ " không bị đột biến. " Nếu bạn có thông tin chỉ ra rằng ý nghĩa đơn giản không phải là những gì Goetz và cộng sự có nghĩa là hãy thêm một câu trả lời và tôi sẽ upvote. –

+0

JCP 3.5.4: Các đối tượng không thay đổi về mặt kỹ thuật, nhưng có trạng thái * sẽ không được sửa đổi * sau khi xuất bản, được gọi là không thay đổi có hiệu quả. - Định nghĩa này bao gồm tập hợp rộng hơn thì đối tượng không có phương thức làm thay đổi trạng thái của chúng. Chỉ cần có convetion rằng các đối tượng không nên bị đột biến sau khi xuất bản an toàn là đủ để có hiệu quả bất biến. –

2

Hãy xem câu trả lời này:

hiệu quả bất biến và bất biến Sự khác biệt giữa hiệu quả bất biến và bất biến là trong trường hợp đầu tiên bạn vẫn cần phải công bố các đối tượng trong một cách an toàn. Đối với các đối tượng thật sự không thay đổi, không cần thiết. Vì vậy, các đối tượng thật sự không thể thay đổi được ưa thích vì chúng dễ xuất bản hơn, lý do tôi đã nói ở trên nói lý do bạn có thể thích xuất bản không đồng bộ.

https://stackoverflow.com/a/7887675/1007546

6

Dưới đây là sự hiểu biết của tôi từ một chút googling và tìm this article. Một đối tượng hiệu quả không thể thay đổi là một đối tượng có chứa các trường có thể bị đột biến, nhưng nó không cho phép bất cứ điều gì thay đổi các trường đó bởi vì nó không bao giờ cung cấp cho bạn một tham chiếu đến chúng. Ví dụ: giả sử bạn tạo một lớp với một số ArrayList trong đó. ArrayList s có thể thay đổi, nhưng nếu lớp của bạn luôn trả về một bản sao của ArrayList và mọi thứ khác trong lớp của bạn là không thay đổi, thì lớp của bạn đã trở thành hiệu quả không thay đổi: Không có cách nào để thay đổi trạng thái của một thể hiện của lớp.

Các bài viết trên blog cho đây là một ví dụ về một lớp học có hiệu quả bất biến:

import java.awt.*; 

public class Line { 

    private final Point start; 
    private final Point end; 

    public Line(final Point start, final Point end) { 
     this.start = new Point(start); 
     this.end = new Point(end); 
    } 

    public void draw() { 
     //... 
    } 

    public Point getStart() { 
     return new Point(start); 
    } 

    public Point getEnd() { 
     return new Point(end); 
    } 
} 

Point đối tượng là có thể thay đổi, nhưng đó là ok, vì lớp này không cung cấp cho tất cả mọi người tham khảo trực tiếp đến trường Point . Thay vào đó, nó trả về một cá thể mới có cùng giá trị trong nó. Bằng cách đó, không ai có thể biến đổi trạng thái của lớp Line. Điều này làm cho lớp Line có hiệu quả bất biến.

Vậy điều này khác với lớp thực sự bất biến như thế nào? Một lớp học thực sự bất biến có các lĩnh vực cũng không thay đổi. Hãy tưởng tượng Line thực sự là bất biến. Để làm điều đó, chúng tôi cũng sẽ phải tưởng tượng rằng Point là không thay đổi. Đưa ra những giả định, phương pháp getStart() văn đều có thể được viết như thế này:

public Point getStart() { 
    return start; 
} 
+0

@Gray xem chỉnh sửa của tôi, cảm ơn –

+0

Thuật ngữ khác nhau, nhưng tôi sẽ xem xét "bất biến hiệu quả" như một đặc tính của đối tượng * thể hiện * thay vì loại. Nếu không có đường dẫn thực thi thông qua đó một tham chiếu đến một cá thể cụ thể nào đó có thể được tiếp xúc với mã có thể làm biến đổi nó, cá thể đó sẽ có hiệu quả bất biến, ngay cả khi lớp của nó không có. Tôi sẽ xem xét một đối tượng chỉ chứa các giá trị và tham chiếu đến các loại bất biến hoặc các trường hợp bất biến có hiệu quả, và không phơi bày bất kỳ phương pháp thay đổi hình dạng riêng của nó, là bất biến. – supercat

+0

@supercat từ nghĩa tiếng Anh của cụm từ, có ý nghĩa. –

1

đối tượng Immutable hoàn toàn gói gọn trạng thái nội bộ của họ và họ không cho phép sửa đổi các trạng thái đó sau khi xây dựng (có thể với việc sử dụng cuối cùng, vv) do đó họ được an toàn để chia sẻ giữa nhiều bài vì đọc từ một đối tượng chia sẻ là không có hại từ nhiều luồng.

Đối tượng không thay đổi có hiệu quả có thể thay đổi trạng thái của chúng trước khi được chia sẻ giữa nhiều luồng, nhưng sau khi chúng được "xuất bản" (nghĩa là nhiều tham chiếu được đưa ra cho một số chủ đề).

Các đối tượng không thể ngăn cản bạn sử dụng các thực hành kỹ thuật phần mềm hữu ích như khởi tạo lười biếng vì để khởi động một thuộc tính hoặc trường, chúng phải có khả năng vi phạm thuộc tính chia sẻ đồng thời vô tư của chúng. Các đối tượng không thay đổi có hiệu quả thư giãn những ràng buộc này để có được cách tiếp cận tốt nhất của cả hai thế giới bằng cách cẩn thận biết khi nào họ có thể sửa đổi trạng thái nội bộ một cách an toàn và khi nó bị cấm.

+0

Có chuỗi là bất biến và ngăn bạn sửa đổi trạng thái nội bộ của nó trực tiếp, nhưng nó sử dụng init lười khi tính hashcode của nó. Vì vậy, về mặt kỹ thuật String có hiệu quả bất biến. – chubbsondubs

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