2010-10-01 22 views
13

tôi có mã như sau:Có luôn luôn là một ý tưởng tồi để sử dụng + để nối chuỗi

String s = ""; 
for (My my : myList) { 
    s += my.getX(); 
} 

FindBugs luôn báo cáo lỗi khi tôi làm điều này.

+1

là getX(); trả về một chuỗi? –

+0

Tôi không nghĩ rằng đó là 'luôn luôn' xấu. Nhưng thường thì không có lựa chọn thay thế nào phù hợp hơn. – decompiled

+6

Chắc chắn không phải là _always bad_ để sử dụng nối với +. Đó là, tuy nhiên, xấu khi bạn đang làm một vòng lặp như thế. – ColinD

Trả lời

21

Tôi sẽ sử dụng + nếu bạn đang tự concatenating,

String word = "Hello"; 
word += " World!"; 

Tuy nhiên, nếu bạn đang đi làm lại và concatenating tôi sẽ đề nghị StringBuilder,

StringBuilder sb = new StringBuilder(); 
for (My my : myList) { 
    sb.append(my.getX()); 
} 
+7

+1 - đó là nối * trong một vòng lặp * mà bạn thường nên tránh. –

+0

Một điểm khác: nó thực sự có thể là _better_ để sử dụng + trong một số trường hợp, nếu có chuỗi ký tự được ghép nối, vì một loạt các chữ ghép nối sẽ được biên dịch thành một chuỗi. Tôi không tích cực, vì cách nó chia thành nhiều dòng, nhưng tôi nghĩ trình biên dịch sẽ tối ưu hóa nó thành 'String word =" Hello World! "'. – ColinD

+0

Bạn có thể sử dụng ghép nối như thế này, nếu bạn chắc chắn rằng không bao giờ, bao giờ ứng dụng của bạn sẽ được bản địa hóa. Nếu bạn đang có kế hoạch dịch nó sang ngôn ngữ nước ngoài, bạn sẽ kết thúc với khiếm khuyết cục bộ. –

8

Đối tượng chuỗi không thay đổi được trong Java. Mỗi + có nghĩa là một đối tượng khác. Bạn có thể sử dụng StringBuffer để giảm thiểu số lượng các đối tượng đã tạo.

+7

Java dịch nối với + để sử dụng một 'StringBuilder'. Bạn chỉ cần sử dụng chính 'StringBuilder' nếu bạn đang lặp hoặc xây dựng một chuỗi bằng cách sử dụng một loạt các cuộc gọi phương thức hoặc một số lệnh như vậy. Ngoài ra, 'StringBuffer' có phí an toàn chủ đề mà bạn thường không cần, do đó,' StringBuilder' thường là một lựa chọn tốt hơn. – ColinD

+5

_Tony scurries đi để đọc về StringBuilder_ –

3

Trình biên dịch có thể tối ưu hóa một số điều như

"foo" + "bar"

Để

StringBuilder s1 = new StringBuilder(); s1.append ("foo"). Chắp thêm ("thanh");

Tuy nhiên điều này vẫn còn tối ưu vì nó bắt đầu với kích thước mặc định là 16. Như với nhiều thứ, bạn nên tìm cổ chai lớn nhất của mình và tìm cách xuống danh sách. Nó không bị tổn thương khi ở trong habbit sử dụng một mẫu SB từ khi bắt đầu, đặc biệt nếu bạn có thể tính toán kích thước khởi tạo tối ưu.

+0

thực sự là * trình biên dịch * có thể tối ưu hóa điều này chỉ với '" foobar "' ... +1 để tìm nút cổ chai –

3

Tối ưu hóa sớm có thể xấu cũng như thường làm giảm khả năng đọc và thường hoàn toàn không cần thiết. Sử dụng + nếu nó dễ đọc hơn trừ khi bạn thực sự có mối quan tâm trọng yếu.

3

Nó không phải là 'luôn luôn xấu' để sử dụng "+". Sử dụng StringBuffer ở khắp mọi nơi có thể làm cho mã thực sự cồng kềnh.

Nếu ai đó đặt nhiều "+" ở giữa vòng lặp chuyên sâu, thời gian quan trọng, tôi sẽ cảm thấy khó chịu. Nếu ai đó đặt rất nhiều "+" trong một đoạn mã hiếm khi được sử dụng, tôi sẽ không quan tâm.

1

Tôi có thể nói sử dụng cộng trong những điều sau đây:

String c = "a" + "b"

Và sử dụng lớp StringBuilder nơi khác. Như đã đề cập trong trường hợp đầu tiên nó sẽ được tối ưu hóa bởi trình biên dịch và nó dễ đọc hơn.

4

Mỗi lần bạn làm string+=string, nó gọi phương pháp như thế này:

private String(String s1, String s2) { 
    if (s1 == null) { 
     s1 = "null"; 
    } 
    if (s2 == null) { 
     s2 = "null"; 
    } 
    count = s1.count + s2.count; 
    value = new char[count]; 
    offset = 0; 
    System.arraycopy(s1.value, s1.offset, value, 0, s1.count); 
    System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); 
} 

Trong trường hợp của StringBuilder, nói đến:

final void append0(String string) { 
    if (string == null) { 
     appendNull(); 
     return; 
    } 
    int adding = string.length(); 
    int newSize = count + adding; 
    if (newSize > value.length) { 
     enlargeBuffer(newSize); 
    } 
    string.getChars(0, adding, value, count); 
    count = newSize; 
} 

Như bạn có thể kết luận rõ ràng, string + string tạo ra rất nhiều trên không, và theo ý kiến ​​của tôi nên tránh nếu có thể.Nếu bạn nghĩ rằng sử dụng StringBuilder là cồng kềnh hoặc để lâu bạn chỉ có thể thực hiện một phương pháp và sử dụng nó một cách gián tiếp, như:

public static String scat(String... vargs) { 
    StringBuilder sb = new StringBuilder(); 

    for (String str : vargs) 
     sb.append(str); 

    return sb.toString(); 
} 

Và sử dụng nó như:

String abcd = scat("a","b","c","d"); 

Trong C# Tôi đang nói về mình giống như string.Concat();. Trong trường hợp của bạn nó sẽ là khôn ngoan để viết quá tải cho SCAT, như:

public static String scat(Collection<?> vargs) { 
    StringBuilder sb = new StringBuilder(); 

    for (Object str : vargs) 
     sb.append(str); 

    return sb.toString(); 
} 

Sau đó, bạn có thể gọi nó với:

result = scat(myList) 
1

Một trong những lý do tại sao FindBugs nên tranh luận về việc sử dụng toán tử nối (được nó "+" hoặc "+ =") là khả năng cục bộ. Trong ví dụ này bạn đã cho nó không phải là quá rõ ràng, nhưng trong trường hợp của đoạn mã sau đó là:

String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses"; 

Nếu điều này có vẻ hơi quen thuộc, bạn cần thay đổi phong cách mã hóa của bạn. Vấn đề là, nó sẽ âm thanh tuyệt vời bằng tiếng Anh, nhưng nó có thể là một cơn ác mộng đối với người dịch. Đó là bởi vì bạn không thể đảm bảo rằng thứ tự của câu sẽ vẫn như cũ sau khi dịch - một số ngôn ngữ sẽ được dịch sang "1 blah blah", một số thành "blah blah 3". Trong những trường hợp như vậy, bạn nên luôn sử dụng MessageFormat.format() để xây dựng các câu ghép và sử dụng toán tử nối là lỗi quốc tế hóa rõ ràng.

BTW. Tôi đặt một lỗi i18n khác ở đây, bạn có thể phát hiện ra nó không?

0

Thời gian chạy của hai chuỗi là tỷ lệ thuận với độ dài của chuỗi. Nếu nó được sử dụng trong một thời gian chạy vòng lặp luôn luôn tăng lên. Vì vậy, nếu nối là cần thiết trong một vòng lặp của nó tốt hơn để sử dụng StringBuilder như Anthony đề nghị.

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