2010-05-09 31 views
9

Dưới đây là một ví dụ về một phương pháp hữu ích:Phương thức tiện ích - Truyền tệp hoặc chuỗi?

public static Long getFileSize(String fileString) { 

    File file = new File(fileString); 

    if (file == null || !file.isFile()) 
     return null; 

    return file.length(); 
} 

Có một thực hành tốt để vượt qua một chuỗi chứ không phải là một tập tin đến một phương pháp như thế này? Nói chung lý do gì nên được áp dụng khi thực hiện các phương pháp tiện ích của phong cách này?

+3

Nếu họ đang tạo một 'File' trước, tôi không nghĩ họ sẽ làm phiền' getFileSize (file) 'khi họ chỉ có thể làm' file.length() '. Ngoài ra, 'file' không thể là' null' trong tình huống đó; các hàm tạo không có khả năng trả về một đối tượng null, nó sẽ phải là một phương thức factory như 'File makeFile (String filename)' –

Trả lời

3

Đây là giải pháp của tôi ưa thích:

public static Long getFileSize(String path) { 
    return getFileSize(new File(path)); 
} 

public static Long getFileSize(File file) { 
    return (!file.isFile()) ? -1L : file.length(); 
} 

Lưu ý rằng nó đang trở lại -1L hơn 0l, cho phép người gọi để phân biệt giữa một tập tin rỗng, và một "tập tin" có chiều dài không thể được xác định cho một số lý do. file.length() sẽ trả về 0 trong một số trường hợp mà bạn không có tệp có độ dài bằng 0; ví dụ.

  • khi file không tồn tại
  • khi file là một thư mục
  • khi file là một tập tin đặc biệt (ví dụ tập tin thiết bị, đường ống, vv) và hệ điều hành không thể xác định chiều dài của nó.

Giao dịch cuộc gọi file.isFile() với các trường hợp này. Tuy nhiên, có thể gây tranh cãi cho dù phương pháp (s) nên trả lại -1L hoặc ném một ngoại lệ. Câu trả lời cho cuộc tranh luận này cho biết các trường hợp -1L là "bình thường" hoặc "ngoại lệ" và chỉ có thể được xác định có tham chiếu đến các ngữ cảnh trong đó phương pháp được thiết kế để sử dụng,

0

Điều duy nhất quan trọng là bạn sẽ sử dụng phương pháp này như thế nào. Nói cách khác, nếu ứng dụng của bạn hoạt động với các đối tượng File, bạn có thể vượt qua chúng và loại bỏ một số hoạt động không cần thiết. Nếu bạn hoạt động với đường dẫn tệp, thông số chuỗi có thể thuận tiện hơn.

Nhưng cuối cùng, lựa chọn không đúng: không làm cho ứng dụng của bạn hoạt động kém hơn.

1

Tôi nghĩ điều này sẽ phụ thuộc vào những gì bạn có sẵn tại thời điểm bạn định gọi phương thức này. Nếu bạn có tên tệp (Chuỗi), nhưng không có Tệp, có vẻ như ít điểm trong việc khiến người gọi tạo Tệp từ tên tệp.

Cách tiếp cận của tôi với điều này khi tôi không chắc chắn là tạo hai phương pháp, một cho String, một cho Tệp. Sau đó, String tạo một tập tin và gọi tập tin.

public static long getFileSize (final String fileString) { 
    return getFileSIze (new File (fileString)); 
} 

public static long getFileSize (File file) { 
    if (file == null || !file.isFile()) return null; 
    return file.length(); 
} 
1

Tùy thuộc vào tiện ích được mong đợi từ phía máy khách. Trong trường hợp phía máy khách đã có đối tượng tệp và muốn tìm nạp tệp, trình phát triển phía máy khách buộc phải trích xuất đường dẫn tệp và chuyển nó tới phương thức tiện ích. Để tránh nó, tôi sẽ cung cấp các phương thức quá tải 1) với File 2) Đường dẫn tệp tin

Ngoài ra, trong trường hợp tệp không khả dụng, tôi sẽ ném ngoại lệ hơn trả về null.

+0

Không có lợi thế nào trong quá tải ở đây, sử dụng các tên riêng biệt trừ khi có một số biện minh. http://stackoverflow.com/questions/248222/method-overloading-can-you-overuse-it – leonbloy

+0

@leonbloy - Bạn sẽ cân nhắc điều gì? Ví dụ: trong câu hỏi bạn đã liên kết, câu trả lời được chấp nhận sẽ đề xuất rõ ràng quá tải, trong số những thứ khác, tên tệp là chuỗi và Tệp. – CPerkins

+0

@CPerkins: xem câu trả lời của tôi cho binil và câu trích từ Joshua Bloch. Phương thức nạp chồng (với cùng số tham số) là gốc của nhiều tệ nạn đặc biệt khi: các kiểu thay thế là một lớp con khác hoặc khi được sử dụng trong các bộ định tuyến (hoặc trong các phương thức chung mà một số khung sẽ tra cứu trong thời gian chạy qua phản xạ). Tôi đồng ý rằng những yếu tố xấu đi này không áp dụng ở đây, nhưng dù sao, tôi bảo thủ về điều này, và không đồng ý với đề xuất đó. – leonbloy

1

Tôi đề nghị là nên có cả hai:

public static Long getFileSize(String path) { 
    return getFileSize(new File(path)); 
} 

public static Long getFileSize(File file) { 
    return (file == null || !file.isFile()) ? 0L : file.length(); 
} 

và cho phép người dùng của bạn lựa chọn dựa trên các loại đối tượng họ đang sử dụng để đại diện cho đường dẫn hệ thống tập tin. Như @Nikita đã đề cập, không phải lựa chọn nào là sai.

+2

Tôi sẽ cung cấp cho bạn +1 ... nếu nó không phải là thử nghiệm 'file == null'. Trường hợp đó là lỗi thiết kế theo phương thức gốc ... nó chỉ cho phép NPE xảy ra.) Ngoài ra, bạn nên trả về -1L thay vì 0L cho "không phải tệp" để phân biệt trường hợp tệp có byte không. –

+1

@Stephen Vâng, tôi đồng ý với mọi thứ ..ngoại trừ phần +1. :-) –

+0

Quá tải phương pháp thường xuyên bị lạm dụng, và đây là một ví dụ. Không có gì để đạt được (ngoại trừ một số cơn đau trong tương lai) bằng cách gọi hai phương thức giống nhau trong trường hợp này. Đọc ở đây http://stackoverflow.com/questions/248222/method-overloading-can-you-overuse-it – leonbloy

1

Theo ý kiến ​​của tôi, hàm đó chỉ hữu ích với tham số chuỗi. Nó làm gì?

  • Nó tạo đối tượng tệp.
  • Kiểm tra xem nó có thể được tạo ra không.
  • Kiểm tra rằng đó là một tập tin
  • Returns chiều dài

Nếu bạn thông qua nó một tập tin, điều đầu tiên là không cần thiết, hai tiếp theo có lẽ nên được giả định, và chiều dài là thành viên tập chức năng. Nếu bạn chuyển thông tin này một tập tin, chức năng này trở nên quá tầm thường để viết :)

(Ngoài ra, tôi nghĩ trở về null từ một hàm trả về một chặng đường dài là lạ)

Nếu bạn có một đối tượng tập tin đã có, sử dụng :

length = file.isFile() ? file.length() : -1; 

Nếu mã của bạn đề với tệp thay vì tên tệp, bạn có thể tự lưu một số tệp nếu bạn sử dụng lại con trỏ Tệp. Trong trường hợp đó, nó có thể dẫn bạn sử dụng chúng theo cách tiếp cận tên tệp.

+0

Mã đó không mở tệp! Nó tạo ra một "wrapper String lạ mắt" (đối tượng 'File') và sử dụng nó để tra cứu tệp trong hệ thống tệp (trong' isFile() 'và' length() '). Vì tra cứu là bản địa, tôi không biết liệu có thể tiết kiệm thời gian hay tài nguyên hay không bằng cách sử dụng lại đối tượng 'File'. –

+0

@Christian Semrau: Tôi không quá quen thuộc với java, cảm ơn vì đã chỉ ra điều đó. Rõ ràng File() không thực hiện cuộc gọi hệ thống. Nhưng isFile & length cả kết quả trong các cuộc gọi hệ thống (phải không?). Nếu bạn đang làm việc với các đối tượng tệp ở nơi khác, có thể bạn đã biết liệu isFile có được gọi là ... có lẽ bạn không muốn tất cả mã của bạn kiểm tra isFile() và xử lý các thư mục khác nhau. (câu trả lời cố định) – Stephen

1

Có một số cân nhắc:

  1. Phương pháp tiện ích tồn tại để giảm số lượng mã đĩa lặp lại trong ứng dụng của bạn, do đó làm cho mã dễ đọc hơn và giảm số lỗi tiềm ẩn. Nó có ý nghĩa để phục vụ cho các mẫu sử dụng phổ biến nhất, tức là nếu hầu hết thời gian bạn có một chuỗi mô tả một tệp - truyền chuỗi đó. Hầu hết các lợi ích đến từ việc có một phương pháp tiện ích ở một nơi đầu tiên, không nhận được chữ ký tối ưu là 100% bằng chứng trong tương lai.

  2. Việc chuyển một tệp thay vì chuỗi cung cấp khả năng nhập mạnh hơn, tức là bạn có thể kiểm tra nhiều mã của bạn hơn tại thời điểm biên dịch bảo vệ chống lại lỗi chính tả. Làm cho trình biên dịch thực hiện công việc cho bạn, sử dụng lợi ích của việc gõ mạnh.

  3. Truyền tệp có nghĩa là bạn có thể truyền bất kỳ loại đối tượng Tệp nào, có thể là đối tượng tệp trong bộ nhớ riêng mà không phải thay đổi phương thức tiện ích để xử lý bộ mô tả tệp được đặt riêng.

  4. Việc truyền một chuỗi có thể hữu ích khi bạn phải giải quyết rất nhiều với đường dẫn tệp OS và bạn chỉ muốn kiểm tra kích thước với số dòng tối thiểu.

  5. Cuối cùng, bạn có thể có một số phương pháp tiện ích quá tải với chi phí rất thấp. Kịch bản này chính xác là lý do cho sự tồn tại của quá tải phương thức như một tính năng ngôn ngữ. Xem những gì tự nhiên hoạt động trong cơ sở mã của bạn. Mã là dễ uốn và đây không phải là một trong những quyết định thiết kế mà bạn phải sống mãi mãi, trừ khi bạn đang xây dựng một API cho người khác sử dụng.

  6. Bạn cũng có thể muốn thay đổi tên để được mô tả nhiều hơn một chút, ví dụ

    • dài sizeFromFile (File f)
    • sizeFromFileName dài (String name)

    sử dụng quy ước ban đầu suggested by Joel Spolsky.

2

Tôi muốn sử dụng Tệp. Nó cảm thấy một chút OOP chính xác với tôi: nhiều an toàn hơn (Strings rất 'chung' trong Java ...) và ngữ nghĩa biểu cảm: nếu bạn đang xử lý các tệp, sau đó chuyển đối tượng Tệp.

Nhớ lại rằng trong Java một file đối tượng đại diện không thực sự là một tập tin của riêng mình (nội dung của nó) mà là con đường của nó: "An abstract representation of file and directory pathnames" (thậm chí nó có thể là con đường của một tập tin không tồn tại) và đó gần như chính xác những gì bạn cần ở đây.

Điều này chỉ có thể là giới hạn trong một vài trường hợp: nếu "tệp" thực sự là một loại tệp giả hoặc tài nguyên, ví dụ bên trong tệp jar. Cách thay thế tôi thấy hữu ích là URI, trong đó (khái niệm) bao gồm Tệp dưới dạng trường hợp đặc biệt, nhưng cũng có các tài nguyên khác.

Và nếu bạn quyết định gắn bó với hai lựa chọn thay thế (Chuỗi hoặc Tệp), tôi nhấn mạnh không khuyên bạn nên đặt tên cho các phương thức giống nhau. Method overloading can be a pain, chỉ sử dụng nó khi nó mang lại cho bạn một lợi ích hữu hình.

1

Phương pháp Quá tải là cách thực hành tốt nhất trong các trường hợp như vậy.

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