2010-05-23 33 views
9

Chúng ta có thể hạn chế việc tạo đối tượng của một lớp bằng cách làm cho hàm tạo riêng của nó. Nhưng nhà xây dựng này vẫn có thể được gọi từ bên trong lớp. Có cách nào để ngăn chặn điều này trong Java không?Ngăn chặn cuộc gọi của một hàm tạo riêng từ bên trong lớp trong Java

Cảm ơn.

+0

Bạn có thể sử dụng Aspectj để đảm bảo điều đó. Tuy nhiên, nó chỉ nên làm như vậy trừ khi bạn sẽ muốn điều này trên nhiều hơn một nơi, vì nó sẽ thêm một sự phụ thuộc rất lớn và phức tạp. Thường xuyên hơn không, tiêu chuẩn và thực hành sẽ phục vụ bạn tốt hơn về trường hợp này thay vì công cụ và kiểm soát. –

+12

Chúng tôi ném một UnsupportedOperationException từ các nhà xây dựng riêng của chúng tôi mà không có nghĩa là để được khởi tạo. Trên thực tế, thành ngữ đó rất phổ biến đối với chúng ta khi các IDE của chúng ta được cấu hình để chúng ta gõ * pct * (bốn phím bấm) và nó tạo ra một hàm tạo riêng ném một UnsupportedOperationException. – SyntaxT3rr0r

Trả lời

14

Không, không có cách nào để làm điều này. Và thực sự tôi không thể nhìn thấy một lý do để làm như vậy. Bởi vì nếu constructor là private, điều này có nghĩa là anh ta chỉ có thể được gọi từ mã trong lớp chính xác này (không có lớp con, hoặc các lớp khác trong gói), vì vậy nếu bạn không muốn constructor được gọi, hãy đặt chú thích vào nó mà nói như vậy.

Vì mọi người có thể sử dụng hàm tạo sẽ có thể loại bỏ bất kỳ biện pháp nào bạn đặt ở đó để ngăn chặn việc gọi hàm tạo, nó sẽ không có tác dụng thực sự.

Bên cạnh đó, nếu bạn cần một singleton, thì bạn có thể muốn hàm tạo được chạy ít nhất một lần (trừ khi ý tưởng của bạn về một singleton là một lớp thuần túy tĩnh).

+0

Ném ngoại lệ có thể ngăn chặn nó và nó là cách sạch sẽ. Bạn thậm chí có thể viết kiểm tra cho nó. Bất kỳ ai cũng có thể gọi nó từ bên trong lớp hoặc bằng sự phản chiếu và ngoại lệ sẽ vẫn bị ném. Vì vậy, đó là một lý do để làm như vậy: phản ánh. – Ewoks

3

Không, không có cách nào để thực thi một phiên bản duy nhất của một loại cụ thể. Bạn có thể đến gần nhất, như bạn mô tả, làm cho hàm tạo riêng tư để chỉ các hàm trong lớp đó mới có thể gọi nó. Bạn có thể làm điều gì đó trong thời gian chạy (chẳng hạn như ném một ngoại lệ nếu trường hợp tĩnh của bạn đã tồn tại), nhưng điều đó sẽ không giúp bạn có được gì ở thời gian biên dịch.

6

Câu trả lời chính thức là không. Nếu bất cứ ai có thể có quyền truy cập riêng vào lớp của bạn, anh ta có thể khởi tạo nó.

Tuy nhiên bạn có thể làm điều này:

private static int count = 0; 

private MyClass(){ 
    if(++count>1)throw new IllegalStateException(); //allow exactly one instantiation 
} 
+0

Ý tưởng đúng, nhưng điều này cần đồng bộ hóa để được chống đạn. Bạn có thể muốn sử dụng một CountDownLatch cho điều này nếu đi theo cách này. –

+0

Sai lần nữa ..... – duffymo

+1

Không chắc chắn nên nói duffymo, sau khi đọc lại OP, đây là câu trả lời đúng nhất ở đây (thực sự, để phù hợp với yêu cầu của OP, nó chỉ nên ném một ngoại lệ, nhưng điều này cho thấy làm thế nào bạn vẫn có thể thực thi điều kiện này trong khi cho phép một trường hợp đơn lẻ, đó là một kịch bản thực tế hơn.) Nếu bạn tin rằng câu hỏi là vô nghĩa, đó là một bình luận về câu hỏi, không phải là câu trả lời. Nhưng câu hỏi không có câu trả lời. –

9

Nếu đó là riêng tư và bạn không muốn nó được gọi là trong phạm vi lớp học riêng của mình, có một cách dễ dàng để ngăn chặn một điều như vậy: Đừng viết mã gọi nó nhiều hơn một lần. Bạn là tác giả của lớp. Tại sao bạn viết mã để ngăn cản bản thân làm điều gì đó nằm trong tầm kiểm soát của bạn?

Không thể gọi bên ngoài lớp học mà không cần phải phản ánh. Nếu bạn không muốn nó được gọi là nhiều hơn một lần trong lớp học, sau đó chỉ cần không làm điều đó. Tại sao viết mã để ngăn chặn một hành động mà bạn có thể chọn không làm?

Hãy xem xét lại:

Chúng ta có thể resrict việc tạo ra các đối tượng của một lớp bằng cách làm cho constructor của tư nhân.

Constructor là riêng tư, vì vậy không thể gọi bên ngoài lớp trừ khi khách hàng sử dụng API phản chiếu để làm suy yếu các hạn chế truy cập.

Nhưng hàm tạo này vẫn có thể là được gọi từ trong vòng lớp. Có bất kỳ nào để ngăn chặn điều này trong Java không?

OP yêu cầu ngăn chặn gọi hàm tạo bị hạn chế bên trong lớp học.

Nếu hai câu lệnh này là chính xác, vui lòng giải thích lý do tại sao cần phải ngăn chặn logic cuộc gọi đến hàm tạo.

Dưới đây là một sử dụng điển hình của một nhà xây dựng tư nhân:

public class Singleton 
{ 
    private static final Singleton instance = new Singleton(); 

    public static void main(String[] args) 
    { 
     Singleton singleton = Singleton.getInstance(); 

     System.out.println(singleton); 
    } 

    private Singleton() {}; 

    public static Singleton getInstance() { return Singleton.instance; } 

    public String toString() { return Singleton.class.getName(); } 
} 

Tôi không thể nhìn thấy điểm của không cho phép các cuộc gọi đến các nhà xây dựng tư nhân.

+0

Nhưng mỗi lớp sẽ có ít nhất một hàm tạo, và có vẻ như câu hỏi đang hạn chế các cuộc gọi đến nó bên trong lớp. –

+4

Có, nhưng nếu bạn đọc câu trả lời của tôi, bạn sẽ nhận ra câu hỏi vô lý như thế nào. Bỏ phiếu xuống của bạn không được bảo đảm. – duffymo

+1

Trình xây dựng cần vẫn được viết, bởi vì nếu không có hàm tạo, trình biên dịch sẽ thêm một trình công khai, điều này thậm chí còn tồi tệ hơn. – Alfonso

2

Nếu bạn đang thực hiện một singleton, enums là cách tốt nhất để đi:

public enum MySingleton { 
    INSTANCE; 
    // add methods & stuff here 
} 

// Usage: 
MySingleton.INSTANCE.doSomething(); 

Các "singletonicity" được đảm bảo bởi JVM - có sẽ chỉ là một ví dụ.

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