Câu trả lời:
Vấn đề duy nhất với nó là nó làm tắc nghẽn không gian tên cục bộ của bạn. Ví dụ: giả sử bạn đang viết một ứng dụng Xoay, và do đó cần java.awt.Event
, và cũng đang can thiệp vào hệ thống lịch của công ty com.mycompany.calendar.Event
. Nếu bạn nhập cả hai bằng phương thức ký tự đại diện, một trong ba điều sau sẽ xảy ra:
java.awt.Event
và com.mycompany.calendar.Event
, và do đó bạn thậm chí không thể biên dịch..*
), nhưng đó là sai và bạn đấu tranh để tìm ra lý do tại sao mã của bạn tuyên bố loại đó là sai.com.mycompany.calendar.Event
, nhưng khi chúng thêm mã sau đó, mã hợp lệ trước đó của bạn đột nhiên dừng biên dịch.Ưu điểm của việc liệt kê rõ ràng tất cả các nhập khẩu là tôi có thể biết trong nháy mắt bạn muốn sử dụng lớp nào, điều này chỉ đơn giản làm cho việc đọc mã dễ dàng hơn nhiều. Nếu bạn chỉ làm một việc nhanh chóng, không có gì sai rõ ràng , nhưng những người bảo trì trong tương lai sẽ cảm ơn bạn vì sự rõ ràng của bạn nếu không.
Đây là một cuộc bỏ phiếu cho nhập khẩu sao. Một câu lệnh nhập được dự định để nhập một gói , không phải là một lớp. Nó là sạch hơn nhiều để nhập khẩu toàn bộ gói; các vấn đề được xác định ở đây (ví dụ java.sql.Date
vs java.util.Date
) dễ dàng được khắc phục bằng các phương thức khác, không thực sự được giải quyết bằng cách nhập khẩu cụ thể và chắc chắn không biện minh cho việc nhập khẩu khủng khiếp trên tất cả các lớp. Không có gì đáng lo ngại hơn việc mở một tệp nguồn và phải trang qua 100 câu lệnh nhập.
Làm nhập khẩu cụ thể làm cho tái cấu trúc khó khăn hơn; nếu bạn xóa / đổi tên một lớp, bạn cần xóa tất cả các mục nhập cụ thể của nó. Nếu bạn chuyển đổi một triển khai sang một lớp khác trong cùng một gói, bạn phải đi sửa lỗi nhập. Mặc dù các bước bổ sung này có thể được tự động hóa, nhưng chúng thực sự là những cú đánh năng suất mà không có lợi ích thực sự.
Ngay cả khi Eclipse không thực hiện nhập lớp theo mặc định, mọi người vẫn sẽ thực hiện nhập sao. Tôi xin lỗi, nhưng thực sự không có lý do hợp lý nào cho việc nhập khẩu cụ thể.
Đây là cách giải quyết các xung đột trong lớp:
import java.sql.*;
import java.util.*;
import java.sql.Date;
Foo
và nếu tôi đọc mã của bạn mà không sử dụng IDE (vì đối số của bạn là tôi không nên sử dụng một), làm sao tôi biết gói nào Foo
đến từ ? Chắc chắn, bằng cách sử dụng một IDE, IDE sẽ cho tôi biết, nhưng toàn bộ đối số của bạn là tôi sẽ có thể đọc mã mà không cần một mã. Thực hiện nhập khẩu rõ ràng giúp ghi lại mã (lý do tuyệt vời để tránh ký tự đại diện) và nhiều khả năng tôi sẽ đọc mã mà không sử dụng IDE, hơn là tôi sẽ viết mã mà không sử dụng IDE.
vui lòng xem bài viết của tôi Nhập khẩu theo yêu cầu là xấu xa
Nói tóm lại, vấn đề lớn nhất là mã của bạn có thể bị hỏng khi một lớp được thêm vào gói bạn nhập. Ví dụ:
import java.awt.*;
import java.util.*;
// ...
List list;
Trong Java 1.1, điều này là tốt; Danh sách đã được tìm thấy trong java.awt và không có xung đột.
Bây giờ, giả sử bạn kiểm tra mã làm việc hoàn hảo của mình và một năm sau, một người khác sẽ mang nó ra để chỉnh sửa nó và đang sử dụng Java 1.2.
Java 1.2 đã thêm một giao diện có tên List vào java.util. BÙM! Cuộc xung đột. Mã làm việc hoàn hảo không còn hoạt động.
Đây là một tính năng ngôn ngữ EVIL . Có NO lý do rằng mã nên dừng biên dịch chỉ vì một loại được thêm vào một gói ...
Ngoài ra, nó khiến người đọc khó xác định "Foo" nào bạn đang sử dụng.
java.util.List
vs java.awt.List
không quá tệ để tìm ra, nhưng hãy thử nó khi tên lớp Configuration
và nhiều thư viện phụ thuộc đã thêm nó trong phiên bản maven repo mới nhất của họ.
Nó không xấu sử dụng một thẻ hoang dã với một tuyên bố nhập khẩu Java.
Trong Clean Code , Robert C. Martin thực sự khuyên bạn nên sử dụng chúng để tránh danh sách nhập khẩu dài.
Đây là khuyến nghị:
J1: Tránh danh sách nhập dài bằng cách sử dụng ký tự đại diện
Nếu bạn sử dụng hai hoặc nhiều lớp từ một gói, sau đó nhập toàn bộ gói với
gói nhập khẩu. *;
Danh sách dài hàng nhập khẩu đang làm nản lòng người đọc. Chúng tôi không muốn làm lộn xộn các mô-đun của chúng tôi với 80 dòng nhập khẩu. Thay vào đó, chúng tôi muốn nhập khẩu là một tuyên bố ngắn gọn về những gói chúng tôi cộng tác.
Nhập khẩu cụ thể là phụ thuộc cứng, trong khi nhập khẩu ký tự đại diện thì không. Nếu bạn đặc biệt nhập một lớp, thì lớp đó phải tồn tại. Nhưng nếu bạn nhập một gói với ký tự đại diện, không có lớp cụ thể nào cần tồn tại. Câu lệnh nhập chỉ đơn giản là thêm gói vào đường dẫn tìm kiếm khi săn tên. Vì vậy, không có sự phụ thuộc thực sự được tạo ra bởi các nhập khẩu như vậy và do đó chúng phục vụ để giữ cho các mô-đun của chúng tôi ít kết nối hơn.
Có những lúc danh sách dài nhập khẩu cụ thể có thể hữu ích. Ví dụ: nếu bạn đang xử lý mã kế thừa và bạn muốn tìm hiểu những lớp nào bạn cần để xây dựng mô hình và sơ khai, bạn có thể xem danh sách các nhập khẩu cụ thể để tìm ra tên đủ điều kiện thực sự của tất cả các lớp đó và sau đó đặt các cuống thích hợp tại chỗ. Tuy nhiên, việc sử dụng này cho nhập khẩu cụ thể là rất hiếm. Hơn nữa, hầu hết các IDE hiện đại sẽ cho phép bạn chuyển đổi các nhập khẩu có ký tự đại diện sang một danh sách các nhập khẩu cụ thể bằng một lệnh duy nhất. Vì vậy, ngay cả trong trường hợp kế thừa, tốt hơn là nhập ký tự đại diện.
Nhập ký tự đại diện đôi khi có thể gây ra xung đột tên và sự mơ hồ. Hai lớp có cùng tên, nhưng trong các gói khác nhau, sẽ cần phải được nhập cụ thể hoặc ít nhất là đủ điều kiện cụ thể khi được sử dụng. Điều này có thể gây phiền toái nhưng hiếm khi sử dụng nhập khẩu ký tự đại diện vẫn tốt hơn so với nhập khẩu cụ thể.
Hiệu suất : Không ảnh hưởng đến hiệu suất vì mã byte là như nhau. mặc dù nó sẽ dẫn đến một số chi phí biên dịch.
Biên dịch : trên máy cá nhân của tôi, Biên dịch một lớp trống mà không nhập bất cứ thứ gì mất 100 ms nhưng cùng một lớp khi nhập java. * Mất 170 ms.
import java.*
Nhập khẩu không có gì. Tại sao nó sẽ làm cho một sự khác biệt?
Nó làm tắc nghẽn không gian tên của bạn, yêu cầu bạn chỉ định đầy đủ bất kỳ tên lớp nào không rõ ràng. Sự xuất hiện phổ biến nhất của điều này là với:
import java.util.*;
import java.awt.*;
...
List blah; // Ambiguous, needs to be qualified.
Nó cũng giúp làm cho các phụ thuộc của bạn cụ thể, vì tất cả các phụ thuộc của bạn được liệt kê ở đầu tệp.
Hầu hết các nơi tôi từng làm việc sử dụng bất kỳ lượng Java đáng kể nào đều biến nhập khẩu rõ ràng thành một phần của tiêu chuẩn mã hóa. Thỉnh thoảng tôi vẫn sử dụng * để tạo mẫu nhanh và sau đó mở rộng danh sách nhập (một số IDE cũng sẽ làm điều này cho bạn) khi sản xuất mã.
Trong một dự án trước đây, tôi thấy rằng việc thay đổi từ * nhập khẩu sang nhập khẩu cụ thể đã giảm một nửa thời gian biên dịch (từ khoảng 10 phút xuống còn khoảng 5 phút). * -Import làm cho trình biên dịch tìm kiếm từng gói được liệt kê cho một lớp khớp với lớp bạn đã sử dụng. Trong khi thời gian này có thể nhỏ, nó bổ sung cho các dự án lớn.
Một tác động phụ của * -import là các nhà phát triển sẽ sao chép và dán các dòng nhập chung thay vì nghĩ về những gì họ cần.
Trong sách DDD
Trong bất kỳ công nghệ phát triển nào, việc triển khai sẽ dựa trên, hãy tìm cách giảm thiểu công việc tái cấu trúc MODULES. Trong Java, không có lối thoát nào khi nhập vào các lớp riêng lẻ, nhưng ít nhất bạn có thể nhập toàn bộ các gói cùng một lúc, phản ánh ý định rằng các gói là các đơn vị gắn kết cao đồng thời giảm nỗ lực thay đổi tên gói.
Và nếu nó làm tắc nghẽn không gian tên cục bộ thì đó không phải là lỗi của bạn - đổ lỗi cho kích thước của gói.
Không có tác động thời gian chạy, vì trình biên dịch sẽ tự động thay thế * bằng các tên lớp cụ thể. Nếu bạn dịch ngược tệp. Class, bạn sẽ không bao giờ thấy import ...*
.
C # luôn sử dụng * (ngầm) vì bạn chỉ có thể using
gói tên. Bạn không bao giờ có thể chỉ định tên lớp ở tất cả. Java giới thiệu tính năng này sau c #. (Java rất phức tạp về nhiều mặt nhưng nó nằm ngoài chủ đề này).
Trong Intellij Idea khi bạn thực hiện "tổ chức nhập", nó sẽ tự động thay thế nhiều lần nhập của cùng một gói bằng *. Đây là một tính năng bắt buộc vì bạn không thể tắt nó (mặc dù bạn có thể tăng ngưỡng).
Các trường hợp được liệt kê bởi trả lời được chấp nhận là không hợp lệ. Không có * bạn vẫn gặp vấn đề tương tự. Bạn cần chỉ định tên pakcage trong mã của mình cho dù bạn có sử dụng * hay không.
Đối với bản ghi: Khi bạn thêm một lần nhập, bạn cũng cho biết sự phụ thuộc của mình.
Bạn có thể thấy nhanh sự phụ thuộc của các tệp (không bao gồm các lớp có cùng không gian tên).
Điều quan trọng nhất là việc nhập java.awt.*
có thể làm cho chương trình của bạn không tương thích với phiên bản Java trong tương lai:
Giả sử rằng bạn có một lớp có tên là "ABC", bạn đang sử dụng JDK 8 và bạn nhập java.util.*
. Bây giờ, giả sử rằng Java 9 xuất hiện và nó có một lớp mới trong gói java.util
mà do sự trùng hợp ngẫu nhiên cũng được gọi là "ABC". Chương trình của bạn bây giờ sẽ không biên dịch trên Java 9, vì trình biên dịch không biết nếu với tên "ABC", bạn có nghĩa là lớp của riêng bạn hoặc lớp mới trongjava.awt
.
Bạn sẽ không gặp vấn đề đó khi bạn chỉ nhập các lớp đó một cách rõ ràng từ java.awt
đó bạn thực sự sử dụng.
Tài nguyên:
Stream
làm ví dụ về một lớp mới được thêm vào Java trong java.util trong Java 8 ...
Trong số tất cả các điểm hợp lệ được thực hiện ở cả hai phía, tôi không tìm thấy lý do chính của mình để tránh ký tự đại diện: Tôi muốn có thể đọc mã và biết trực tiếp mọi lớp là gì, hoặc nếu định nghĩa đó không phải là ngôn ngữ hoặc các tập tin, nơi để tìm thấy nó. Nếu có nhiều hơn một gói được nhập với * Tôi phải tìm kiếm từng gói để tìm một lớp tôi không nhận ra. Khả năng đọc là tối cao và tôi đồng ý mã không nên yêu cầu IDE để đọc nó.