2012-05-29 51 views
20

Hôm nay, một người nào đó đã tham dự tôi sử dụng sai từ khóa return trong Java. Tôi đã viết một vòng lặp đơn giản for để xác thực điều gì đó nằm trong một mảng. Giả array là một mảng có độ dài n này là mã của tôi:trả lại cho vòng lặp hoặc vòng lặp ngoài

for(int i=0; i<array.length; ++i){ 
    if(array[i]==valueToFind) return true; 
} 
return false; 

Bây giờ ai đó nói với tôi rằng đây không phải là chương trình rất tốt vì tôi sử dụng câu lệnh return bên trong một vòng lặp và điều này sẽ gây ra thu gom rác thải bị trục trặc. Do đó mã tốt hơn sẽ là:

int i = 0; 
while(i<array.length && array[i] != valueToFind) ++i; 
return i != array.length; 

Vấn đề là tôi không thể tìm ra lý do tại sao vòng lặp đầu tiên không phải là một thực hành tốt. Ai đó có thể cho tôi một sự thôi thúc không?

+0

Chính xác thì người đó đã đưa ra lý do gì cho người đầu tiên không ổn? Messes với GC? – Poindexter

+7

Nếu GC có trục trặc, đó là vấn đề của JVM, không phải của chương trình ... Mã của bạn hoàn toàn hợp lệ. –

+0

"điều này sẽ khiến bộ sưu tập rác bị trục trặc": Bạn có thể xây dựng được không? – assylias

Trả lời

47

Bây giờ ai đó nói với tôi rằng đây không phải là chương trình rất tốt vì tôi sử dụng câu lệnh return bên trong một vòng lặp và điều này sẽ gây ra thu gom rác thải bị trục trặc.

Điều đó không đúng và gợi ý bạn nên đối xử với lời khuyên khác từ người đó với mức hoài nghi.

Câu thần chú "chỉ có một câu trả lời" (hoặc thường chỉ có một điểm thoát) quan trọng bằng các ngôn ngữ mà bạn phải tự quản lý tất cả tài nguyên - theo cách đó bạn có thể đảm bảo mã ở một nơi.

Nó ít hữu ích hơn nhiều trong Java: ngay sau khi bạn biết rằng bạn nên quay trở lại (và giá trị trả về sẽ là gì), chỉ cần trả về. Bằng cách đó, việc đọc sách đơn giản hơn - bạn không phải thực hiện bất kỳ phần còn lại nào của phương pháp để tìm ra điều gì khác sẽ xảy ra (ngoài các khối finally).

+4

Một câu lệnh trả về duy nhất là một phần của quy ước mã nơi tôi đã từng làm việc. Tôi tìm thấy nó dẫn đến rất nhiều làm tổ và khó khăn hơn để đọc mã. – brain

+2

@brain: Thật vậy. Nó thường là kết quả của những người tham gia vào một ý tưởng mà không hiểu lý do * * tại sao nó là một ý tưởng tốt trong một bối cảnh nhất định. –

+1

Trong trường hợp có ngoại lệ, một lối thoát duy nhất chỉ là không thể thực hiện được, vì hầu như bất kỳ đoạn mã nontrivial nào cũng có thể tăng lên. Tốt hơn là nên đi với luồng ngôn ngữ ở đây thay vì buộc mã hoạt động theo một số quy tắc có thể có ý nghĩa trong môi trường/ngôn ngữ khác. –

6

Bây giờ ai đó nói với tôi rằng đây không phải là chương trình rất tốt bởi vì tôi sử dụng câu lệnh return bên trong một vòng lặp và điều này sẽ gây ra rác bộ sưu tập để trục trặc.

Đó là một đống rác. Tất cả mọi thứ bên trong phương pháp sẽ được làm sạch trừ khi có các tham chiếu khác cho nó trong lớp hoặc ở nơi khác (một lý do tại sao đóng gói là quan trọng). Theo quy tắc chung, tốt hơn hết nên sử dụng một câu lệnh trả về đơn giản vì dễ dàng tìm ra phương thức sẽ thoát.

Cá nhân, tôi sẽ viết:

Boolean retVal = false; 
for(int i=0; i<array.length; ++i){ 
    if(array[i]==valueToFind) { 
     retVal = true; 
     break; //Break immediately helps if you are looking through a big array 
    } 
} 
return retVal; 
+5

Meh; nói chung là tốt hơn để viết mã dễ đọc nhất, bất kể điều đó có nghĩa là gì đối với số báo cáo trả về. Ví dụ, nếu bạn có một loạt các điều khoản bảo vệ, mỗi (IMO) sẽ trở lại ngay lập tức trên thất bại. –

+0

Như một lưu ý phụ, không có gì để GC trong phương pháp này, vì không có phân bổ đối tượng ở đây. –

+0

Chắc chắn đồng ý với Dave - Tôi không hiểu tại sao "nơi mà phương pháp sẽ thoát" là bất kỳ tầm quan trọng nào. Điều quan trọng là làm thế nào bạn có thể dễ dàng theo logic của phương pháp. –

3

Đã có phương pháp trong tất cả các ngôn ngữ ủng hộ cho việc sử dụng một câu lệnh return duy nhất trong bất kỳ chức năng. Tuy nhiên không thể nó có thể ở trong một số mã, một số người cố gắng làm điều đó, tuy nhiên, nó có thể làm cho mã của bạn trở nên phức tạp hơn (như trong nhiều dòng mã), nhưng mặt khác, dễ theo dõi hơn (như trong logic lưu lượng).

Điều này sẽ không làm hỏng bộ sưu tập rác theo bất kỳ cách nào !!

Cách tốt nhất để làm điều đó là đặt giá trị boolean, nếu bạn muốn nghe anh ấy.

boolean flag = false; 
for(int i=0; i<array.length; ++i){ 
    if(array[i] == valueToFind) { 
     flag = true; 
     break; 
    } 
} 
return flag; 
2

Một số người cho rằng phương pháp nên có một điểm thoát duy nhất (ví dụ: chỉ một return).Cá nhân, tôi nghĩ rằng cố gắng gắn bó với quy tắc đó tạo ra mã khó đọc hơn. Trong ví dụ của bạn, ngay sau khi bạn tìm thấy những gì bạn đang tìm kiếm, hãy trả lại ngay lập tức, nó rõ ràng và hiệu quả.

Quoting the C2 wiki:

Ý nghĩa ban đầu của việc có một mục duy nhất và thoát duy nhất cho một chức năng là nó là một phần của định nghĩa ban đầu của StructuredProgramming như trái ngược với SpaghettiCode goto vô kỷ luật, và cho phép phân tích toán học sạch trên cơ sở đó. Bây giờ, lập trình có cấu trúc từ lâu đã giành được ngày, không ai đặc biệt quan tâm đến điều đó nữa, và phần còn lại của trang chủ yếu là về thực tiễn tốt nhất và tính thẩm mỹ và không, về phân tích toán học của các cấu trúc lập trình có cấu trúc.

1

Mã hợp lệ (nghĩa là, sẽ biên dịch và thực thi) trong cả hai trường hợp.

Một trong những giảng viên của tôi tại Uni nói với chúng tôi rằng nó không phải là mong muốn có continue, return tuyên bố trong bất kỳ vòng lặp - for hoặc while. Lý do cho điều này là khi kiểm tra mã, nó không phải là không ngay lập tức rõ ràng cho dù chiều dài đầy đủ của vòng lặp sẽ được thực hiện hoặc return hoặc continue sẽ có hiệu lực.

Xem Why is continue inside a loop a bad idea? để biết ví dụ. Điều quan trọng cần ghi nhớ là đối với các tình huống đơn giản như thế này không phải vấn đề (IMO) nhưng khi bạn có logic phức tạp xác định giá trị trả về, thì mã "thường" dễ đọc hơn nếu bạn có một báo cáo trả về thay vì một vài câu lệnh.

Liên quan đến Bộ sưu tập rác - Tôi không biết tại sao điều này lại là vấn đề.

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