Hàm thay thế cho từ khóa goto trong Java là gì?
Vì Java không có goto.
Hàm thay thế cho từ khóa goto trong Java là gì?
Vì Java không có goto.
Câu trả lời:
Bạn có thể sử dụng câu lệnh BREAK được gắn nhãn :
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length; j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
break search;
}
}
}
Tuy nhiên, trong mã được thiết kế phù hợp, bạn không cần chức năng GOTO.
Không có bất kỳ tương đương trực tiếp nào với goto
khái niệm trong Java. Có một số cấu trúc cho phép bạn thực hiện một số điều bạn có thể làm với cổ điển goto
.
break
và continue
cho phép bạn nhảy ra khỏi một khối trong một vòng lặp hoặc câu lệnh chuyển đổi.break <label>
cho phép bạn nhảy ra khỏi một câu lệnh ghép tùy ý đến bất kỳ mức nào trong một phương thức nhất định (hoặc khối khởi tạo).continue <label>
tiếp tục với lần lặp tiếp theo của vòng lặp bên ngoài từ vòng lặp bên trong.return
.Không có cấu trúc Java nào trong số này cho phép bạn rẽ nhánh ngược hoặc tới một điểm trong mã ở cùng cấp độ lồng như câu lệnh hiện tại. Tất cả chúng đều nhảy ra một hoặc nhiều cấp độ (phạm vi) lồng nhau và tất cả chúng (ngoài continue
) đều nhảy xuống dưới. Hạn chế này giúp tránh hội chứng goto "mã spaghetti" vốn có trong mã BASIC, FORTRAN và COBOL cũ 2 .
1- Phần tốn kém nhất của các ngoại lệ là việc tạo thực tế đối tượng ngoại lệ và ngăn xếp của nó. Nếu bạn thực sự, thực sự cần sử dụng xử lý ngoại lệ cho điều khiển luồng "bình thường", bạn có thể phân bổ trước / sử dụng lại đối tượng ngoại lệ hoặc tạo một lớp ngoại lệ tùy chỉnh ghi đè fillInStackTrace()
phương thức. Nhược điểm là các printStackTrace()
phương thức của ngoại lệ sẽ không cung cấp cho bạn thông tin hữu ích ... nếu bạn cần gọi chúng.
2 - Hội chứng mã spaghetti sinh ra phương pháp lập trình có cấu trúc , nơi bạn hạn chế sử dụng các cấu trúc ngôn ngữ có sẵn. Điều này có thể được áp dụng cho BASIC , Fortran và COBOL , nhưng nó đòi hỏi sự cẩn thận và kỷ luật. Loại bỏ goto
hoàn toàn là một giải pháp thực dụng tốt hơn. Nếu bạn giữ nó trong một ngôn ngữ, luôn có một số tên hề sẽ lạm dụng nó.
Nói cho vui, đây là cách triển khai GOTO trong Java.
Thí dụ:
1 public class GotoDemo { 2 public static void main(String[] args) { 3 int i = 3; 4 System.out.println(i); 5 i = i - 1; 6 if (i >= 0) { 7 GotoFactory.getSharedInstance().getGoto().go(4); 8 } 9 10 try { 11 System.out.print("Hell"); 12 if (Math.random() > 0) throw new Exception(); 13 System.out.println("World!"); 14 } catch (Exception e) { 15 System.out.print("o "); 16 GotoFactory.getSharedInstance().getGoto().go(13); 17 } 18 } 19 }
Chạy nó:
$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo 3 2 1 0 Hello World!
Tôi có cần thêm "không sử dụng nó!"?
Math.random()
có thể trở lại 0. Nó phải là> =
Trong khi một số người bình luận và người phản đối cho rằng đây không phải là goto , mã bytecode được tạo ra từ các câu lệnh Java bên dưới thực sự gợi ý rằng những câu lệnh này thực sự diễn đạt ngữ nghĩa goto .
Cụ thể, do {...} while(true);
vòng lặp trong ví dụ thứ hai được tối ưu hóa bởi trình biên dịch Java để không đánh giá điều kiện của vòng lặp.
label: {
// do stuff
if (check) break label;
// do more stuff
}
Trong bytecode:
2 iload_1 [check]
3 ifeq 6 // Jumping forward
6 ..
label: do {
// do stuff
if (check) continue label;
// do more stuff
break label;
} while(true);
Trong bytecode:
2 iload_1 [check]
3 ifeq 9
6 goto 2 // Jumping backward
9 ..
continue label
là bước nhảy lùi
// do stuff
và // do more stuff
là các câu lệnh quan tâm, continue label
"có tác dụng" nhảy ngược lại (do while(true)
câu lệnh tất nhiên). Tuy nhiên, tôi không biết rằng đây là một câu hỏi chính xác như vậy ...
while(true)
được dịch bởi trình biên dịch thành một goto
hoạt động bytecode. Như true
một nghĩa đen không đổi, trình biên dịch có thể thực hiện việc tối ưu hóa này và không phải đánh giá bất cứ điều gì. Vì vậy, ví dụ của tôi thực sự là một con goto, nhảy ngược ...
Nếu bạn thực sự muốn một cái gì đó giống như câu lệnh goto, bạn luôn có thể thử phá vỡ các khối được đặt tên.
Bạn phải ở trong phạm vi của khối để phá vỡ nhãn:
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
Tôi sẽ không giảng cho bạn lý do tại sao bạn nên tránh goto - Tôi cho rằng bạn đã biết câu trả lời cho điều đó.
public class TestLabel {
enum Label{LABEL1, LABEL2, LABEL3, LABEL4}
/**
* @param args
*/
public static void main(String[] args) {
Label label = Label.LABEL1;
while(true) {
switch(label){
case LABEL1:
print(label);
case LABEL2:
print(label);
label = Label.LABEL4;
continue;
case LABEL3:
print(label);
label = Label.LABEL1;
break;
case LABEL4:
print(label);
label = Label.LABEL3;
continue;
}
break;
}
}
public final static void print(Label label){
System.out.println(label);
}
StephenC viết:
Có hai cấu trúc cho phép bạn thực hiện một số điều bạn có thể làm với goto cổ điển.
Một lần nữa...
Matt Wolfe viết:
Mọi người luôn nói về việc không bao giờ sử dụng goto, nhưng tôi nghĩ rằng có một trường hợp sử dụng thực sự tốt trong thế giới thực khá nổi tiếng và được sử dụng. Đó là, đảm bảo thực thi một số mã trước khi trả về từ một hàm .. Thường là việc phát hành khóa hoặc không, nhưng trong trường hợp của tôi, tôi muốn có thể nghỉ ngơi ngay trước khi quay lại để tôi có thể thực hiện dọn dẹp bắt buộc.
try {
// do stuff
return result; // or break, etc.
}
finally {
// clean up before actually returning, even though the order looks wrong.
}
http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
Khối cuối cùng luôn thực thi khi khối try thoát. Điều này đảm bảo rằng khối cuối cùng được thực thi ngay cả khi một ngoại lệ không mong muốn xảy ra. Nhưng cuối cùng hữu ích cho nhiều hơn là chỉ xử lý ngoại lệ - nó cho phép lập trình viên tránh việc mã dọn dẹp vô tình bị bỏ qua khi trả về, tiếp tục hoặc ngắt. Đặt mã dọn dẹp trong một khối cuối cùng luôn là một phương pháp hay, ngay cả khi không có ngoại lệ nào được dự đoán trước.
Câu hỏi phỏng vấn ngớ ngẩn được liên kết với cuối cùng là: Nếu bạn quay lại từ khối try {}, nhưng cũng có lợi nhuận trong khối {} cuối cùng, thì giá trị nào được trả về?
return
một finally
khối vào một khối là một ý tưởng tồi. (Và thậm chí nếu những kiến thức không phải là thực sự cần thiết, tôi muốn được lo lắng bởi một lập trình viên người không có sự tò mò để tìm hiểu ...)
Hãy thử mã bên dưới. Nó làm việc cho tôi.
for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is 8 Taksa
strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];
LabelEndTaksa_Exit : {
if (iCountTaksa == 1) { //If count is 6 then next it's 2
iCountTaksa = 2;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 2) { //If count is 2 then next it's 3
iCountTaksa = 3;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 3) { //If count is 3 then next it's 4
iCountTaksa = 4;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 4) { //If count is 4 then next it's 7
iCountTaksa = 7;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 7) { //If count is 7 then next it's 5
iCountTaksa = 5;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 5) { //If count is 5 then next it's 8
iCountTaksa = 8;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 8) { //If count is 8 then next it's 6
iCountTaksa = 6;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 6) { //If count is 6 then loop 1 as 1 2 3 4 7 5 8 6 --> 1
iCountTaksa = 1;
break LabelEndTaksa_Exit;
}
} //LabelEndTaksa_Exit : {
} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"
Java không có goto
, bởi vì nó làm cho mã không có cấu trúc và không rõ ràng để đọc. Tuy nhiên, bạn có thể sử dụng break
và continue
như một hình thức văn minh của goto mà không gặp vấn đề gì.
ahead: {
System.out.println("Before break");
break ahead;
System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");
Đầu ra :
Before Break
After ahead
before: {
System.out.println("Continue");
continue before;
}
Điều này sẽ dẫn đến một vòng lặp vô hạn vì mỗi khi dòng continue before
được thực thi, dòng mã sẽ bắt đầu lại từ đóbefore
.
goto
có trong Java không? Tôi nghĩ trong đó nằm ở vấn đề quan trọng hơn.