Đối với một thách thức, một golfer mã đồng nghiệp đã viết mã sau đây :
import java.util.*;
public class Main {
public static void main(String[] args) {
int size = 3;
String[] array = new String[size];
Arrays.fill(array, "");
for(int i = 0; i <= 100; ) {
array[i++%size] += i + " ";
}
for(String element: array) {
System.out.println(element);
}
}
}
Khi chạy mã này trong Java 8, chúng tôi nhận được kết quả sau:
1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 100
2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99
Khi chạy mã này trong Java 10, chúng tôi nhận được kết quả sau:
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 102
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
Việc đánh số hoàn toàn tắt khi sử dụng Java 10. Vậy điều gì đang xảy ra ở đây? Đây có phải là một lỗi trong Java 10 không?
Theo dõi từ các ý kiến:
- Vấn đề xuất hiện khi được biên dịch bằng Java 9 trở lên (chúng tôi đã tìm thấy nó trong Java 10). Biên dịch mã này trên Java 8, sau đó chạy trong Java 9 hoặc bất kỳ phiên bản nào mới hơn, bao gồm cả truy cập sớm Java 11, sẽ cho kết quả như mong đợi.
- Loại mã này là không chuẩn, nhưng hợp lệ theo thông số kỹ thuật. Nó được Kevin Cruijssen tìm thấy trong một cuộc thảo luận trong một thử thách chơi gôn , do đó đã gặp phải trường hợp sử dụng kỳ lạ.
Didier L phát hiện ra rằng vấn đề có thể được sao chép với mã nhỏ hơn và dễ hiểu hơn nhiều:
class Main { public static void main(String[] args) { String[] array = { "" }; array[test()] += "a"; } static int test() { System.out.println("evaluated"); return 0; } }
Kết quả khi được biên dịch trong Java 8:
evaluated
Kết quả khi được biên dịch trong Java 9 và 10:
evaluated evaluated
Vấn đề này dường như bị giới hạn ở những nối chuỗi và toán tử gán (
+=
) với một biểu thức với tác dụng phụ (s) là toán hạng bên trái, như trongarray[test()]+="a"
,array[ix++]+="a"
,test()[index]+="a"
, hoặctest().field+="a"
. Để cho phép nối chuỗi, ít nhất một trong hai bên phải có kiểuString
. Cố gắng tái tạo điều này trên các loại hoặc cấu trúc khác không thành công.
+=
áp dụng cho các String
tài liệu tham khảo gián tiếp . Vì vậy, đầu tiên, mảng của bạn phải là một String[]
. Vấn đề không xảy ra với int[]
, long[]
và bạn bè. Nhưng vâng, về cơ bản là bạn đúng!
String[]
. Nếu nó là Object[]
và bạn làm array[expression] += "foo";
, nó là như nhau. Nhưng có, nó không áp dụng cho mảng nguyên thủy, vì nó phải có khả năng giữ tham chiếu của kiểu String
( Object[]
, CharSequence[]
, Comparable[]
, ...), để lưu trữ các kết quả của chuỗi nối.