Integer.toString (int i) vs String.valueOf (int i)


175

Tôi đang tự hỏi tại sao phương pháp String.valueOf(int i)tồn tại? Tôi đang sử dụng phương pháp này để chuyển đổi intthành Stringvà chỉ phát hiện ra Integer.toString(int i)phương thức.

Sau khi xem xét việc thực hiện các phương pháp này, tôi thấy rằng phương thức thứ nhất đang gọi phương thức thứ hai. Kết quả là tất cả các cuộc gọi của tôi String.valueOf(int i)liên quan đến một cuộc gọi nhiều hơn là gọi trực tiếpInteger.toString(int i)


3
Chỉ dành cho mục đích tham khảo: stackoverflow.com/questions/3335685/integer-tostring
Bobby

Câu trả lời:


46

Chỉ cần hai cách khác nhau để làm điều tương tự. Nó có thể là một lý do lịch sử (không thể nhớ nếu người này đến trước người kia).


22
Có, nhưng nếu một cái gì đó đang làm như vậy, không có nghĩa đó là điều tương tự.
Damian Leszczyński - Vash

3
String.valueOf (int) chỉ cần gọi trực tiếp Integer.toString (i). Vì vậy, tốt nhất để gọi Integer.toString (int).
djchapm

171

Trong kiểu String, chúng ta có một số phương thức valueOf

static String   valueOf(boolean b) 
static String   valueOf(char c) 
static String   valueOf(char[] data) 
static String   valueOf(char[] data, int offset, int count) 
static String   valueOf(double d) 
static String   valueOf(float f) 
static String   valueOf(int i) 
static String   valueOf(long l) 
static String   valueOf(Object obj) 

Như chúng ta có thể thấy các phương thức đó có khả năng giải quyết tất cả các loại số

mọi cách thực hiện phương pháp cụ thể như bạn đã trình bày: Vì vậy, đối với số nguyên chúng tôi có

Integer.toString(int i)

cho đôi

Double.toString(double d)

và như thế

Theo tôi đây không phải là một điều lịch sử, nhưng nó hữu ích hơn cho nhà phát triển sử dụng phương thức valueOftừ lớp String hơn là từ loại thích hợp, vì nó dẫn đến ít thay đổi hơn cho chúng ta thực hiện.

Mẫu 1:

public String doStuff(int num) {

  // Do something with num...

  return String.valueOf(num);

 }

Mẫu2:

public String doStuff(int num) {

 // Do something with num...

 return Integer.toString(num);

 }

Như chúng ta thấy trong mẫu 2, chúng ta phải thực hiện hai thay đổi, ngược lại với mẫu một.

Theo kết luận của tôi, sử dụng valueOfphương thức từ lớp String linh hoạt hơn và đó là lý do tại sao nó có sẵn ở đó.


18
Và đừng quên Integer.toString(int i, int radix)rằng sẽ chuyển đổi thành chuỗi các căn cứ khác ngoài 10.
Stephen P

@Vash Bạn có thể vui lòng giải thích về việc sử dụng chuỗi rỗng để chuyển đổi int thành Chuỗi so với String.valueOf không? ví dụ: "" + int i = "i"? Tốt nhất ?
Kanagavelu Sugumar

1
Để định dạng int dưới dạng chuỗi, bạn không nên sử dụng "" + i. Không tồn tại lớn trên đầu nhưng nói chung vì điều này không thanh lịch. Thay vì sử dụng String.valueOf(int), bạn có thể sử dụng String.format("%d",i);để đọc thêm, vui lòng truy cập trang web docs.oracle.com/javase/6/docs/api/java/util/Formatter.html
Damian Leszczyński - Vash

Tôi muốn autoboxing thông minh hơn và chỉ cần thêm chuyển đổi trên trình biên dịch hoặc một cái gì đó.
Rob Grant

1
@RobertGrant Việc autoboxing không phải là trường hợp ở đây. Nhưng để trả lời mối quan tâm của bạn, thật thông minh khi bạn có thể làm điều này int i = new Integer("1");và ngược lại.
Damian Leszczyński - Vash

52

Một sự khác biệt lớn là nếu bạn gọi toString()một đối tượng null, bạn sẽ nhận được một NullPointerExceptiontrong khi đó, sử dụng String.valueOf()bạn có thể không kiểm tra null.


46
Câu hỏi là về Integer.toString(int i), một staticphương pháp. Không có nullđối tượng có thể.
Petr Janeček

14
Integer i = null; i.toString(); // Null pointer exception!! String.valueOf(i); // No exception
manish_s

10
@Manis Kumar: Ví dụ của bạn sẽ không kích hoạt String.valueOf(int i)phương thức nhưng String.valueOf(Object obj). Dù sao, câu hỏi là về các intgiá trị nguyên thủy , nơi không có khả năng null.
hleinone

1
@manish_s khá rõ ràng từ ví dụ rằng không ai nói về Integer loại Object. Chúng ta chỉ nói về người nguyên thủy.
Daniel Ochoa

2
@manish_s: OP không nói Integer.toString()nhưng Integer.toString(int i). Đó là một phương thức tĩnh ( docs.oracle.com/javase/7/docs/api/java/lang/ mẹo ).
LarsH

13

Lớp String cung cấp các phương thức valueOf cho tất cả các kiểu nguyên thủy và kiểu Object, vì vậy tôi giả sử chúng là các phương thức tiện lợi mà tất cả có thể được truy cập thông qua một lớp.

Kết quả hồ sơ NB

Trung bình intToString = 5368ms, Chuỗi trung bìnhValueOf = 5689ms (cho 100.000.000 hoạt động)

public class StringIntTest {


    public static long intToString () {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = Integer.toString(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static long stringValueOf () {

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            String j = String.valueOf(i);
        }
        long finishTime = System.currentTimeMillis();

        return finishTime - startTime;
    }

    public static void main(String[] args) {
        long intToStringElapsed = 0;
        long stringValueOfElapsed = 0;
        for (int i = 0; i < 10; i++) {
            intToStringElapsed += intToString();
            stringValueOfElapsed+= stringValueOf();
        }
        System.out.println("Average intToString = "+ (intToStringElapsed /10));
        System.out.println("Average stringValueOf = " +(stringValueOfElapsed / 10));
    }
}

7
Hồ sơ của bạn nên thực sự có một khoảng thời gian "khởi động", nếu không, kết quả có thể bị sai lệch bởi sự mày mò của JIT với mọi thứ. Điều đó nói rằng, chênh lệch 300ms so với 10 ^ 8 thao tác là quá nhỏ đến mức không đáng kể.
Cameron Skinner

1
@Kingo Tôi không nghĩ trường hợp thử nghiệm của bạn là chính xác. Bởi vì bạn đang gán giá trị cho String jnhưng không bao giờ sử dụng. Trình biên dịch cơ bản có thể đã tối ưu hóa điều này. Tốt hơn là truyền đối tượng j trong phương thức khác nhau và thực hiện một số thao tác giả.
Rakesh

1
Bạn thực sự không nên viết điểm chuẩn vi sinh tại nhà theo cách này. Nếu bạn sử dụng JMH . Nó sẽ đảm nhiệm việc khởi động, đo thời gian, thử nhiều lần độc lập (giả sử Java!) Và làm cho mã nhỏ, trông giống như (bao gồm kết quả cho các phương thức và giá trị khác nhau - thời gian chạy 7 phút): gist.github.com/ecki/ 399136f4fd59c1d110c1 (spoiler: "" + n đã thắng).
eckes

5
Cảm ơn bạn, nhưng câu trả lời của tôi là 5 năm trước! JMH chỉ được phát hành vào năm 2013: P
Kingo

9

Từ các nguồn Java:

/**
 * Returns the string representation of the {@code int} argument.
 * <p>
 * The representation is exactly the one returned by the
 * {@code Integer.toString} method of one argument.
 *
 * @param   i   an {@code int}.
 * @return  a string representation of the {@code int} argument.
 * @see     java.lang.Integer#toString(int, int)
 */
public static String valueOf(int i) {
    return Integer.toString(i);
}

Vì vậy, họ đưa ra chính xác cùng một kết quả và thực tế người này gọi người kia. String.valueOf linh hoạt hơn nếu bạn có thể thay đổi loại sau này.


8

Nếu bạn nhìn vào mã nguồn của Stringlớp, nó thực sự gọi Integer.toString()khi bạn gọi valueOf().

Điều đó đang được nói, Integer.toString()có thể nhanh hơn một chút nếu các phương thức gọi không được tối ưu hóa tại thời gian biên dịch (mà chúng có thể là).


Có và "" + n thậm chí còn nhanh hơn. Xem gist.github.com/ecki/399136f4fd59c1d110c1
eckes

3

Việc triển khai String.valueOf()mà bạn thấy là cách đơn giản nhất để đáp ứng hợp đồng được chỉ định trong API: "Đại diện chính xác là cách trả về theo Integer.toString()phương thức của một đối số."


2

Để trả lời câu hỏi của OP, nó chỉ đơn giản là một trình bao bọc trợ giúp để có cuộc gọi khác, và đưa ra lựa chọn kiểu dáng và đó là nó. Tôi nghĩ rằng có rất nhiều thông tin sai lệch ở đây và điều tốt nhất mà một nhà phát triển Java có thể làm là xem xét việc triển khai cho từng phương thức, đó là một hoặc hai lần nhấp trong bất kỳ IDE nào. Bạn sẽ thấy rõ rằng String.valueOf(int)chỉ đơn giản là gọi Integer.toString(int)cho bạn.

Do đó, hoàn toàn không có sự khác biệt, trong đó cả hai đều tạo một bộ đệm char, đi qua các chữ số trong số, sau đó sao chép nó vào một Chuỗi mới và trả về nó (do đó mỗi người đang tạo một đối tượng Chuỗi). Chỉ có sự khác biệt là một cuộc gọi thêm, mà trình biên dịch sẽ loại bỏ một cuộc gọi duy nhất.

Vì vậy, vấn đề không phải là bạn gọi, ngoài khả năng nhất quán mã. Đối với các ý kiến ​​về null, nó cần một nguyên thủy, do đó nó không thể là null! Bạn sẽ gặp lỗi thời gian biên dịch nếu bạn không khởi tạo int được truyền. Vì vậy, không có sự khác biệt trong cách nó xử lý null vì chúng không tồn tại trong trường hợp này.


Bạn có thể vui lòng tách văn bản của bạn thành một số khối. Nó rất khó đọc.
Magnilex

Có rất nhiều điều sai lệch trong OP này. Bài viết của bạn là câu trả lời tốt nhất cho tôi! Cảm ơn bạn
vui mừng

1

Bạn không nên lo lắng về cuộc gọi thêm này làm bạn tốn kém về vấn đề hiệu quả. Nếu có bất kỳ chi phí nào, nó sẽ là tối thiểu và không đáng kể trong bức tranh lớn hơn.

Có lẽ lý do tại sao cả hai tồn tại là để cung cấp khả năng đọc. Trong ngữ cảnh của nhiều loại được chuyển đổi thành String, thì các cuộc gọi khác nhau String.valueOf(SomeType)có thể dễ đọc hơn các SomeType.toStringcuộc gọi khác nhau .


1
Trên thực tế, các cuộc gọi một dòng như vậy được nội tuyến khá nhanh.
Tassos Bassoukos

Ngay cả trong một vòng lặp gọi 1 000 000 thời gian String.valueof () ??
Manuel Selva

@Manuel: bạn đã hồ sơ nó? Bạn đã xác định rằng đây là vấn đề hiệu suất của bạn? Bạn có chắc là bạn không tối ưu sớm? @Tassos: vâng, điều đó cũng rất có khả năng, nhưng dù bằng cách nào tôi cũng không lo lắng về điều đó trừ khi hồ sơ nói rằng có vấn đề với cuộc gọi cụ thể này.
đa gen

Trên thực tế, thưa ông, tôi mong muốn một vòng lặp sẽ đi 1000000 lần để được nội tuyến thường xuyên hơn là chỉ đi một hoặc hai lần. Mặc dù vậy, nó sẽ là một phần nhỏ của thời gian cho dù nó có lặp lại bao nhiêu lần đi chăng nữa.
corsiKa

Không nhưng tôi chắc chắn không có cổ chai ở đây trong ứng dụng của tôi. Tôi chỉ hỏi điều này bởi vì tôi không thể thấy bất kỳ mối quan tâm dễ đọc nào ở đây và do đó tôi nghĩ rằng tôi phải sử dụng mã tối ưu hơn ngay cả khi mức tăng là 0. Bạn có đồng ý không?
Manuel Selva

1

Openion của tôi là valueof () luôn được gọi là toopes () cho đại diện và vì vậy đối với rpresentaion của valueof loại nguyên thủy được khái quát hóa. Và java theo mặc định không hỗ trợ Kiểu dữ liệu nhưng nó xác định công việc của nó với objaect và phân loại tất cả mọi thứ trong cllas object .here Integer.toString (int i) tạo giới hạn chuyển đổi chỉ cho số nguyên.


1

Không có sự khác biệt giữa Integer.toString (5) và String.valueOf (5);

bởi vì String.valueOf trả về:

public static String valueOf(int i) {
    return Integer.toString(i);
}
public static String valueOf(float f) {
    return Float.toString(f);
}

Vân vân..


0

Sử dụng phương thức, String.valueOf () bạn không phải lo lắng về dữ liệu (cho dù đó là int, long, char, char [], boolean, Object), bạn chỉ cần gọi:

  • chuỗi giá trị tĩnhOf ()

sử dụng cú pháp duy nhất String.valueOf () có thể bất cứ điều gì bạn vượt qua khi tham số được chuyển đổi thành Chuỗi và được trả về ..

Mặt khác, nếu bạn sử dụng Integer.toString (), Float.toString (), v.v. (tức là someType.toString ()) thì bạn sẽ phải kiểm tra kiểu dữ liệu của tham số mà bạn muốn chuyển đổi thành chuỗi. Vì vậy, tốt hơn là sử dụng String.valueOf () cho các hội tụ như vậy.

Nếu bạn đang có một mảng của lớp đối tượng chứa các giá trị khác nhau như Integer, Char, Float, v.v. thì bằng cách sử dụng phương thức String.valueOf (), bạn có thể dễ dàng chuyển đổi các phần tử của mảng đó thành dạng String. Ngược lại, nếu bạn muốn sử dụng someType.toString () thì trước tiên, bạn sẽ cần biết về các lớp kiểu dữ liệu của chúng (có thể bằng cách sử dụng toán tử "instanceOf") và sau đó chỉ bạn mới có thể tiến hành đánh máy.

Phương thức String.valueOf () khi được gọi khớp với tham số được truyền (cho dù là Integer, Char, Float, v.v.) và bằng cách sử dụng các lệnh gọi nạp chồng phương thức mà phương thức "valueOf ()" có tham số được khớp, và bên trong phương thức đó là một cuộc gọi trực tiếp đến phương thức "toString ()" tương ứng ..

Vì vậy, chúng ta có thể thấy cách chi phí kiểm tra kiểu dữ liệu và sau đó gọi phương thức "toString ()" tương ứng được loại bỏ. Chỉ cần chúng ta gọi phương thức String.valueOf (), không quan tâm đến những gì chúng ta muốn chuyển đổi thành Chuỗi.

Kết luận: Phương thức String.valueOf () có tầm quan trọng của nó chỉ bằng chi phí của một cuộc gọi nữa.


-3

toString ()

  1. có mặt trong lớp Object, thường được ghi đè trong lớp dẫn xuất
  2. typecast đến lớp thích hợp là cần thiết để gọi phương thức toString ().

giá trị của()

  1. Phương thức tĩnh quá tải hiện diện trong lớp String.
  2. xử lý các kiểu nguyên thủy cũng như các loại đối tượng.

    Integer a = null;
    System.out.println(Integer.toString()) ; NUll pointer exception
    System.out.println(String.valueOf() ; give NULL as value

kiểm tra liên kết này rất tốt http://code4reference.com/2013/06/which-one-is-better-valueof-or-tostring/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.