2009-09-06 30 views
32

Tôi cần trường boolean có thể thay đổi trong Java (Tôi sẽ trả về trường này thông qua phương thức get * sau và có thể sửa đổi trường này). Boolean không hoạt động vì không có phương thức set * nào trong lớp Boolean (tôi sẽ nói rằng Boolean là không thay đổi, bạn chỉ có thể thay đổi tham chiếu, nhưng bạn không thể thay đổi chính đối tượng đó).Trường boolean có thể thay đổi trong Java

Tôi đoán tôi có thể sử dụng mảng Boolean có kích thước 1. Nhưng có lẽ có nhiều giải pháp thanh lịch hơn?

Tại sao Java không có một thứ đơn giản như vậy?

+5

giá trị Boolean thường thử nghiệm các phương pháp sử dụng 'isXXX' thay vì 'getXXX' – pjp

+1

@pjp' isXXX' chỉ dành cho những 'boolean' nguyên thủy. Chúng ta nên dính vào 'getXXX' cho những' Boolean '. –

Trả lời

53

Các lớp không thể thay đổi dễ làm việc hơn. Họ sẽ không bao giờ thay đổi và sẽ không có vấn đề với mã đồng thời. (Về cơ bản, có ít khả năng hơn để phá vỡ chúng.)

Nếu bạn muốn trả về một tham chiếu đến giá trị Boolean, bạn có thể sử dụng java.util.concurrent.atomic.AtomicBoolean nếu bạn đang làm việc với nhiều chủ đề hoặc đồng bằng cũ org.apache.commons.lang.mutable.MutableBoolean.

+2

Tôi đã viết "có thể thay đổi" trong đối tượng bình luận java.lang.String của mình và không thể thay đổi lại. :-) –

+1

cái này là intersting. có lẽ tôi nên thực sự sử dụng AtomicBoolean ... nhờ – javapowered

+0

hm .. đây là những gì tôi đã đọc trong javadoc: "Một AtomicBoolean được sử dụng trong các ứng dụng như cờ cập nhật nguyên tử, và không thể được sử dụng như là một thay thế cho một Boolean." Tại sao? – javapowered

4

Tại sao không sử dụng boolean nguyên thủy?

ví dụ:

private boolean myFlag = false; 

public void setMyFlag(boolean flag) { 
    myFlag = flag; 
} 

Lưu ý phương thức getter của bạn có thể trả về Boolean nếu cần, do sự kỳ diệu của autoboxing. Điều này cho phép dễ dàng thay đổi giữa việc sử dụng nguyên thủy và các đối tượng tương đương của chúng (ví dụ: boolean so với Boolean hoặc int so với Integer).

Vì vậy, để giải quyết lại câu trả lời đã chỉnh sửa của bạn. các phương pháp bạn có sẵn,

public Object getAttribute(String attributeName) 

có thể được triển khai bằng cách trả về một boolean tự động.

+0

tôi không muốn thêm phương pháp đặc biệt để thiết lập một cái gì đó ... tất cả mọi thứ nên được thực hiện thông qua đối tượng trả về từ getAttribute. Điều này là do tôi không muốn thay đổi giao diện lớp phân cấp hàng đầu. tất cả những gì tôi cần là một đối tượng boolean có thể thay đổi được ... tôi nghĩ rằng java.util.concurrent.atomic.AtomicBoolean có thể là lựa chọn đúng đắn – javapowered

+0

Trong khi tôi hiểu những gì bạn đang làm, tôi muốn nói rằng tôi không chắc chắn đây là một thiết kế tốt. Tôi mong đợi đối tượng chứa để xem xét sau khi thao tác các trường, thay vì chuyển chúng sang mã bên thứ 3 để thay đổi. nghĩa là trách nhiệm của đối tượng chứa để chăm sóc các trường của nó và duy trì trạng thái nhất quán, v.v. Chỉ cần một người đứng đầu (bạn có thể làm việc theo những ràng buộc mà tôi không biết), –

+0

tôi đồng ý trong hầu hết các trường hợp chúng ta không nên sử dụng thực hành như vậy. thậm chí báo cáo "findbugs" "Loại mảng trả về" là "thiết kế kém" vì đối tượng có thể được thay đổi bởi bên thứ ba. Nhưng đây là cách nhiều mã đã được viết và tôi chỉ cần thêm vài thứ nữa :) Ngoài tên của trường tôi sẽ rõ ràng rằng nó phải được thay đổi bởi các bên thứ ba, vì vậy tôi nghĩ rằng nó nên không phải là một vấn đề lớn :) – javapowered

4

Còn về việc sử dụng nguyên hàm boolean thì sao?

private boolean value; 

public void setValue(boolean value) { 
    this.value = value; 
} 

public boolean getValue() { 
    return value; 
} 
+0

điều này sẽ làm việc nhưng bạn phải viết hai phương pháp cho từng lĩnh vực. nhưng tôi không muốn thay đổi giao diện hiện có. phương pháp duy nhất tôi có là: đối tượng công cộng getAttrbiute (String attributeName) – javapowered

+2

Thêm khả năng thiết lập mọi thứ _is_, theo nghĩa thông thường, thay đổi giao diện. Vì vậy, tốt nhất là có sự thay đổi giao diện bằng văn bản thực tế để thể hiện và theo dõi thay đổi đó. – soru

+0

@soru +1 Đó là một cách tuyệt vời để suy nghĩ về vấn đề này. – dhable

26

lẽ viết cho mình một lớp wrapper

class BooleanHolder { 
    public boolean value; 
} 

Hoặc tạo ra một lớp người giữ generic (có nghĩa là bạn sẽ phải sử dụng lớp Boolean thay vì nguyên thủy boolean):

class Holder<T> { 
    public T value; 
} 

Bạn sau đó trả về lớp trình bao bọc thay vì chính giá trị, cho phép giá trị bên trong trình bao bọc được sửa đổi.

+4

điều này sẽ hoạt động, nhưng mảng kích thước 1 đơn giản hơn một chút, imho :) – javapowered

+0

Bạn tạo một mảng BooleanHolders nếu bạn cần nhiều hơn 1 – nos

+0

Không cho phép bạn sử dụng nó như boolean. –

-1

Bạn có thực sự nói rằng bạn muốn người gọi có thể sửa đổi giá trị boolean của đối tượng bằng cách thao tác những gì được trả về? Vì vậy mà đối tượng và người gọi sẽ chia sẻ một tham chiếu đến nó?

Chỉ cần để tôi hiểu, đưa ra:

 
class OddClass { 
    private Boolean strangeFlag; 
    public Object getAttrbiute(String attributeName) { 
     if (attributeName.equals("strangeflag")) return (Object)strangeFlag; 
     ... 
    } 
} 

Và sau đó người gọi không:

 
    Boolean manipulableFlag = (Boolean) myOddClass.getAttrbiute ("strangeflag"); 

Và sau đó, nếu người gọi thay đổi giá trị của manipulableFlag, bạn muốn thay đổi điều đó xảy ra trong Ví dụ OddClass, giống như người gọi thay vì sử dụng phương thức setAttrbiute.

Đó có phải là những gì bạn đang yêu cầu không?

Trong trường hợp đó, bạn sẽ cần một lớp chủ, theo đề xuất của Adam.

+0

đúng, bạn hiểu chính xác. lớp chủ sở hữu là cách giải quyết nặng. ít nhất tôi có thể sử dụng mảng một phần tử, nhưng có lẽ java.util.concurrent.atomic.AtomicBoolean là sự lựa chọn tốt nhất – javapowered

19

Nếu bạn đang sử dụng Java 5 hoặc cao hơn sau đó sử dụng AtomicBoolean

+6

@monzonj: Các lớp 'java.util.concurrent' không sử dụng' sync', chúng sử dụng tốt hơn nhiều optmized khóa xây dựng. 'AtomicBoolean' sẽ có một chi phí hiệu năng hoàn toàn không đáng kể khi được sử dụng như là một chứa cho một' boolean'. nếu bạn có thể chứng minh bằng cách khác, xin vui lòng cho chúng tôi thấy. – skaffman

+5

@monzonj: Nó không có chi phí hiệu năng đáng kể trong mọi trường hợp. Ngoài ra còn có rất nhiều thứ để đạt được từ việc sử dụng đúng công cụ cho đúng công việc. Bất kể những gì bạn nghĩ về một số hiệu suất vi hit mà bạn không thể đo lường, lớp học tối ưu hóa cao này đã được tạo ra vì một lý do, tôi nghi ngờ bạn có thể làm tốt hơn. –

+2

@monzonj - xác nhận của bạn rằng * "phép gán nguyên tử chỉ có thể được thực hiện thông qua đồng bộ hóa" * được thông báo sai, tốt nhất là khái niệm * khóa đồng bộ hóa miễn phí * và nếu bạn thực sự xem nguồn cho 'AtomicBoolean', bạn sẽ thấy rằng không có cách nào sử dụng từ khóa 'đồng bộ' ở bất cứ đâu! Bạn đang truyền bá thông tin sai lệch với nhận xét không được cải thiện của bạn ở mức tốt nhất. –

3

Bạn có thể sử dụng một mảng boolean

final boolean[] values = { false }; 
values[0] = true; 
0

Nếu bạn đang sử dụng Android, bạn có thể sử dụng các đối tượng * android.util.Mutable mà bọc các giá trị nguyên thủy khác nhau. Ví dụ, trích dẫn từ nguồn SDK:

public final class MutableBoolean { 
    public boolean value; 

    public MutableBoolean(boolean value) { 
     this.value = value; 
    } 
} 
1

Câu trả lời tôi thích nhất là từ Adam để viết lớp wrapper của riêng bạn ... OK

/* Boolean to be passed as reference parameter */ 
public class Bool { 

    private boolean value; 

    public Bool() { 
     this.value = false; 
    } 

    public boolean is() { 
     return this.value; 
    } 

    public void setTrue() { 
     this.value = true; 
    } 

    public void setFalse() { 
     this.value = false; 
    } 
} 
Các vấn đề liên quan