2008-09-29 27 views
66

PMD sẽ báo cáo vi phạm cho:Tại sao giao diện cho một lớp Java được ưu tiên?

ArrayList<Object> list = new ArrayList<Object>(); 

Vi phạm là "Tránh sử dụng các loại thực hiện như 'ArrayList'; sử dụng giao diện thay thế".

Các dòng sau sẽ sửa lỗi vi phạm:

List<Object> list = new ArrayList<Object>(); 

Tại sao nên sau này với List được sử dụng thay ArrayList?

+0

Xem thêm http: // stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-giao diện – Raedwald

Trả lời

73

Sử dụng giao diện trên các loại bê tông là chìa khóa để đóng gói tốt và cho khớp nối lỏng mã của bạn.

Thậm chí bạn nên thực hiện theo thực tiễn này khi viết API của riêng bạn. Nếu bạn làm như vậy, bạn sẽ thấy sau này sẽ dễ dàng hơn khi thêm các kiểm tra đơn vị vào mã của bạn (sử dụng các kỹ thuật Mocking) và để thay đổi triển khai cơ bản nếu cần trong tương lai.

Đây là một good article về chủ đề này.

Hy vọng điều đó sẽ hữu ích!

27

Điều này được ưu tiên vì bạn tách mã của mình khỏi việc triển khai danh sách. Sử dụng giao diện cho phép bạn dễ dàng thay đổi việc triển khai, ArrayList trong trường hợp này, sang thực thi danh sách khác mà không thay đổi bất kỳ phần còn lại nào của mã miễn là nó chỉ sử dụng các phương thức được định nghĩa trong Danh sách.

5

ArrayList và LinkedList là hai triển khai của Danh sách, đây là một bộ sưu tập các mục được sắp xếp. Logic-khôn ngoan nó không quan trọng nếu bạn sử dụng một ArrayList hoặc một LinkedList, vì vậy bạn không nên hạn chế các loại được điều đó.

Điều này trái ngược với nói, Bộ sưu tập và Danh sách, những thứ khác nhau (Danh sách ngụ ý sắp xếp, Bộ sưu tập không).

0

Nói chung đối với dòng mã của bạn, điều đó không có ý nghĩa khi làm phiền với giao diện. Nhưng, nếu chúng ta đang nói về các API thì có một lý do thực sự tốt. Tôi có lớp học nhỏ

class Counter { 
    static int sizeOf(List<?> items) { 
     return items.size(); 
    } 
} 

Trong trường hợp này là việc sử dụng giao diện bắt buộc. Bởi vì tôi muốn đếm kích thước của mọi triển khai có thể có bao gồm cả tùy chỉnh của riêng tôi. class MyList extends AbstractList<String>....

+0

Nếu bạn mã để triển khai như ArrayList, có mọi khả năng bạn có thể sử dụng các phương pháp triển khai ngay cả khi bạn có thể làm tương tự với phương thức giao diện. Điều này sẽ ràng buộc mã của bạn để triển khai - làm cho việc chuyển đổi giữa các lần triển khai trở nên khó khăn hơn. – Champ

1

Thuộc tính lớp/giao diện của bạn phải được hiển thị thông qua giao diện vì nó cung cấp cho các lớp của bạn một hợp đồng hành vi để sử dụng, bất kể việc triển khai thực hiện.

Tuy nhiên ...

Trong khai báo biến cục bộ, nó làm cho cảm giác ít để làm điều này:

public void someMethod() { 
List theList = new ArrayList(); 
//do stuff with the list 
} 

Nếu nó một biến địa phương, chỉ cần sử dụng các loại. Nó vẫn hoàn toàn upcastable với giao diện thích hợp của nó, và các phương thức của bạn hy vọng chấp nhận các kiểu giao diện cho các đối số của nó, nhưng đối với các biến cục bộ, nó có ý nghĩa tổng thể khi sử dụng kiểu triển khai như một thùng chứa. chức năng cụ thể.

10

Nói chung, tôi đồng ý rằng giao diện tách khỏi triển khai là một điều tốt và sẽ làm cho mã của bạn dễ bảo trì hơn.

Tuy nhiên, có những trường hợp ngoại lệ mà bạn phải xem xét. Việc truy cập các đối tượng thông qua giao diện sẽ thêm một lớp bổ sung mà sẽ làm cho mã của bạn chậm hơn.

Để quan tâm, tôi đã chạy thử nghiệm đã tạo ra mười tỷ truy cập tuần tự cho một ArrayList dài 1 triệu. Trên MacBook 2.4Ghz của tôi, việc truy cập ArrayList thông qua một giao diện Danh sách mất trung bình 2,10 giây, khi khai báo nó thuộc loại ArrayList nó mất trung bình 1,67 giây.

Nếu bạn đang làm việc với danh sách lớn, sâu bên trong một vòng lặp bên trong hoặc chức năng thường gọi là, thì đây là điều cần xem xét.

+0

@Owen: +5 Xem lại đầy đủ: Hiệu suất khác biệt ... Rất bất ngờ –

+2

Câu trả lời này tuy nhiên cho thấy chi phí có thể rất nhỏ: http://stackoverflow.com/questions/890687/overhead-of-implementing-an-interface/891096 # 891096 – Raedwald

+1

Chà! 0,5 giây cho mười tỷ lượt truy cập, tức là 1 truy cập giao diện chậm hơn một nửa nano giây so với quyền truy cập lớp học! Điều này tất nhiên là một lý do để không bao giờ, bao giờ sử dụng giao diện. – Ingo

1

Ngay cả đối với các biến cục bộ, việc sử dụng giao diện qua lớp bê tông sẽ giúp ích. Bạn có thể sẽ gọi một phương thức nằm ngoài giao diện và sau đó rất khó để thay đổi việc thực hiện Danh sách nếu cần. Ngoài ra, tốt nhất nên sử dụng lớp hoặc giao diện ít cụ thể nhất trong tuyên bố. Nếu thứ tự phần tử không quan trọng, hãy sử dụng Bộ sưu tập thay vì Danh sách. Điều đó mang lại cho mã của bạn sự linh hoạt tối đa.

0

Spring framework áp dụng các khái niệm về giao diện thực sự độc đáo - http://www.springframework.org/

Xuân cung cấp việc thực hiện một lớp bê tông thông qua tập tin cấu hình và vì vậy lớp bê tông không cần phải biết bất cứ điều gì ở tất cả về việc thực hiện.

Nghiên cứu về Spring minh họa các ưu điểm của lập trình dựa trên giao diện trong Java.

1

Tại sao danh sách thứ hai có Danh sách được sử dụng thay vì ArrayList?

Đó là một thực hành tốt: Chương trình để giao tiếp chứ không phải là thực hiện

Bằng cách thay thế ArrayList với List, bạn có thể thay đổi List thực hiện trong thời gian tới như sau tùy thuộc vào trường hợp sử dụng doanh nghiệp của bạn.

List<Object> list = new LinkedList<Object>(); 
/* Doubly-linked list implementation of the List and Deque interfaces. 
Implements all optional list operations, and permits all elements (including null).*/ 

HOẶC

List<Object> list = new CopyOnWriteArrayList<Object>(); 
/* A thread-safe variant of ArrayList in which all mutative operations 
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/ 

HOẶC

List<Object> list = new Stack<Object>(); 

/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/ 

HOẶC

một số khác List thực hiện cụ thể.

List giao diện xác định hợp đồng và thực hiện cụ thể List có thể thay đổi. Theo cách này, giao diện và triển khai được kết hợp lỏng lẻo.

liên quan SE câu hỏi:

What does it mean to "program to an interface"?

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