Trong Java, có sự khác biệt nào giữa String.valueOf(Object)và Object.toString()không? Có một quy ước mã cụ thể cho những điều này?
nulllần đầu tiên.
Trong Java, có sự khác biệt nào giữa String.valueOf(Object)và Object.toString()không? Có một quy ước mã cụ thể cho những điều này?
nulllần đầu tiên.
Câu trả lời:
Theo tài liệu Java , String.valueOf()trả về:
nếu đối số là
null, thì một chuỗi bằng"null"; mặt khác, giá trị củaobj.toString()được trả lại.
Vì vậy, không nên thực sự có một sự khác biệt ngoại trừ một lời gọi phương thức bổ sung.
Ngoài ra, trong trường hợp Object#toString, nếu ví dụ là null, một cái NullPointerExceptionsẽ bị ném, vì vậy có thể nói, nó kém an toàn hơn .
public static void main(String args[]) {
String str = null;
System.out.println(String.valueOf(str)); // This will print a String equal to "null"
System.out.println(str.toString()); // This will throw a NullPointerException
}
String.valueOf(null), đó là một NPE. Nó chỉ hoạt động cho các đối tượng là null.
String.valueOf(null)thực sự giải quyết đến valueOf(char[])quá tải. Điều này là do char[]một loại cụ thể hơn Object.
Sự khác nhau giữa String.valueOf (Object) và Object.toString () là:
1) Nếu chuỗi là null,
String.valueOf(Object)sẽ trở lại null, trong khi Object::toString()sẽ ném một ngoại lệ con trỏ null.
public static void main(String args[]){
String str = null;
System.out.println(String.valueOf(str)); // it will print null
System.out.println(str.toString()); // it will throw NullPointerException
}
2) Chữ ký:
Phương thức valueOf () của lớp String là tĩnh. trong khi phương thức toString () của lớp String là không tĩnh.
Chữ ký hoặc cú pháp của phương thức valueOf () của chuỗi được đưa ra dưới đây:
public static String valueOf(boolean b)
public static String valueOf(char c)
public static String valueOf(char[] c)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(float f)
public static String valueOf(double d)
public static String valueOf(Object o)
Chữ ký hoặc cú pháp của toString()phương thức chuỗi được đưa ra dưới đây:
public String toString()
Trong Java, có sự khác biệt nào giữa String.valueOf (Object) và Object.toString () không?
Đúng. (Và hơn thế nữa nếu bạn xem xét quá tải!)
Như javadoc giải thích, String.valueOf((Object) null)sẽ được coi là trường hợp đặc biệt theo valueOfphương thức và giá trị "null"được trả về. Ngược lại, null.toString()sẽ chỉ cung cấp cho bạn một NPE.
Nó chỉ ra rằng String.valueOf(null)(lưu ý sự khác biệt!) Không đưa ra một NPE ... mặc dù javadoc. Lời giải thích không rõ ràng:
Có một số tình trạng quá tải String.valueOf, nhưng có hai điều có liên quan ở đây: String.valueOf(Object)và String.valueOf(char[]).
Trong biểu thức String.valueOf(null) , cả hai quá tải đó đều có thể áp dụng được , vì nullphép gán tương thích với bất kỳ loại tham chiếu nào.
Khi có hai hoặc nhiều hơn quá tải áp dụng , JLS nói rằng quá tải cho loại đối số cụ thể nhất được chọn.
Từ char[] là một kiểu con của Objectnó, nó là cụ thể hơn .
Do đó, String.valueOf(char[])quá tải được gọi là.
String.valueOf(char[])ném một NPE nếu đối số của nó là một mảng null. không giốngString.valueOf(Object) , nó không được coi nulllà một trường hợp đặc biệt.
(Bạn có thể xác nhận điều này bằng cách sử dụng javap -cđể kiểm tra mã của phương thức có String.valueOf(null)cuộc gọi. Quan sát tình trạng quá tải được sử dụng cho cuộc gọi.)
Một ví dụ khác minh họa sự khác biệt trong valueOf(char[])tình trạng quá tải thậm chí rõ ràng hơn:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Có một quy ước mã cụ thể cho những điều này?
Không.
Sử dụng cái nào phù hợp nhất với yêu cầu của bối cảnh bạn đang sử dụng nó. (Bạn có cần định dạng để làm việc chonull không?)
Lưu ý: đó không phải là quy ước mã. Nó chỉ là lập trình thông thường. Điều quan trọng hơn là mã của bạn là chính xác hơn là tuân theo một số quy ước về phong cách hoặc giáo điều "thực hành tốt nhất".
Ý kiến cá nhân:
Một số nhà phát triển có được thói quen xấu là "phòng thủ" chống lại null. Vì vậy, bạn thấy rất nhiều bài kiểm tra cho null và coi null là trường hợp đặc biệt. Ý tưởng dường như ngăn chặn NPE xảy ra.
Tôi nghĩ rằng đây là một ý tưởng tồi. Cụ thể, tôi nghĩ rằng đó là một ý tưởng tồi nếu những gì bạn làm khi bạn tìm thấy mộtnull là cố gắng "làm cho tốt" ... mà không xem xét lý do tại sao có một nullđó.
Nói chung, tốt hơn hết là tránh nullở đó ngay từ đầu ... trừ khi nó nullcó ý nghĩa rất cụ thể trong ứng dụng hoặc thiết kế API của bạn. Vì vậy, thay vì tránh NPE với nhiều mã hóa phòng thủ, tốt hơn là để NPE xảy ra, sau đó theo dõi và khắc phục nguồn không mong muốnnull đã kích hoạt NPE.
Vậy làm thế nào để áp dụng ở đây?
Chà, nếu bạn nghĩ về nó, sử dụng String.valueOf(obj) có thể là một cách "làm cho tốt". Đó là phải tránh. Nếu nó là bất ngờ objđể được nulltrong bối cảnh, nó là tốt hơn để sử dụng obj.toString().
Hầu hết đã được đề cập bởi các câu trả lời khác, nhưng tôi chỉ cần thêm nó cho đầy đủ:
.toString()vì chúng không phải là một triển khai của Objectlớp, vì vậy chỉ String.valueOfcó thể được sử dụng.String.valueOfsẽ biến đổi một đối tượng đã cho là nullChuỗi "null", trong khi đó .toString()sẽ ném a NullPointerException.String.valueOftheo mặc định khi một cái gì đó giống như String s = "" + (...);được sử dụng. Đó là lý do tại sao Object t = null; String s = "" + t;sẽ dẫn đến Chuỗi "null"chứ không phải trong NPE. StringBuilder.append, không String.valueOf. Vì vậy, bỏ qua những gì tôi nói ở đây.Ngoài những thứ đó, đây thực sự là một trường hợp sử dụng trong đó String.valueOfvà.toString() có kết quả khác nhau:
Hãy nói rằng chúng ta có một phương pháp chung như thế này:
public static <T> T test(){
String str = "test";
return (T) str;
}
Và chúng ta sẽ gọi nó với một Integerloại như thế này:Main.<Integer>test() .
Khi chúng ta tạo một Chuỗi với String.valueOfnó hoạt động tốt:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Điều này sẽ xuất test STDOUT.
Với .toString()tuy nhiên, nó sẽ không làm việc:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Điều này sẽ dẫn đến lỗi sau:
java.lang.ClassCastException: lớpjava.lang.Stringkhông thể được chuyển đến lớpjava.lang.Integer
Về lý do tại sao, tôi có thể tham khảo câu hỏi riêng biệt này và câu trả lời của nó . Tuy nhiên, trong ngắn hạn:
.toString()đầu tiên nó sẽ biên dịch và đánh giá các đối tượng, nơi các diễn viên để T(mà là một Stringđể Integercast trong trường hợp này) sẽ dẫn đến việc ClassCastException.String.valueOfnó sẽ thấy chung chung Tnhư Objecttrong quá trình biên dịch và thậm chí không quan tâm đến việc nó là một Integer. Vì vậy, nó sẽ đúc một Objectđến Object(mà trình biên dịch chỉ cần bỏ qua). Sau đó, nó sẽ sử dụng String.valueOf(Object), dẫn đến một Stringmong đợi. Vì vậy, mặc dù nội bộ String.valueOf(Object)sẽ thực hiện một .toString()tham số trong nội bộ, chúng tôi đã bỏ qua các diễn viên và nó được đối xử như một Object, vì vậy chúng tôi đã tránh được ClassCastExceptionđiều đó xảy ra với việc sử dụng .toString().Chỉ cần nghĩ rằng nó là giá trị đề cập đến sự khác biệt bổ sung giữa String.valueOfvà .toString()ở đây là tốt.
("" + x)được biên dịch String.valueOf(x), nhưng bất cứ điều gì phức tạp hơn đều sử dụng một StringBuffer(chúng tôi không có StringBuildersau đó).
String.valueOf(Object)và Object.toString()theo nghĩa đen là điều tương tự.
Nếu bạn xem qua việc triển khai String.valueOf (Object) , bạn sẽ thấy String.valueOf(Object)về cơ bản đó chỉ là một lời gọi null an toàn của toString()đối tượng thích hợp:
Returns the string representation of the Object argument.
Parameters:
obj an Object.
Returns:
if the argument is null, then a string equal to "null";
otherwise, the value of obj.toString() is returned.
See also:
Object.toString()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Sự khác biệt quan trọng nhất là cách họ xử lý các tham chiếu Chuỗi null.
String str = null;
System.out.println("String.valueOf gives : " + String.valueOf(str));//Prints null
System.out.println("String.toString gives : " + str.toString());//This would throw a NullPointerExeption
Có một sự khác biệt lớn hơn giữa hai phương thức là khi đối tượng chúng ta đang chuyển đổi là một mảng.
Khi bạn chuyển đổi một mảng bằng Object.toString (), bạn sẽ nhận được một số loại giá trị rác (@ theo sau là mã băm của mảng).
Để có được một toString () có thể đọc được của con người, bạn phải sử dụng String.valueOf (char []); Xin lưu ý rằng phương pháp này chỉ hoạt động đối với Mảng kiểu char. Tôi khuyên bạn nên sử dụng Arrays.toString (Object []) để chuyển đổi mảng thành Chuỗi.
Sự khác biệt thứ hai là khi đối tượng là null, ValueOf () trả về một chuỗi "null", trong khi toString () sẽ trả về ngoại lệ con trỏ null.
Tôi không thể nói chính xác sự khác biệt là gì nhưng dường như có sự khác biệt khi hoạt động ở mức byte. Trong kịch bản mã hóa sau đây Object.toString () đã tạo ra một giá trị không thể giải mã được trong khi String.valueOf () hoạt động như dự định ...
private static char[] base64Encode(byte[] bytes)
{
return Base64.encode(bytes);
}
private static String encrypt(String encrypt_this) throws GeneralSecurityException, UnsupportedEncodingException
{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
//THIS FAILED when attempting to decrypt the password
//return base64Encode(pbeCipher.doFinal(encrypt_this.getBytes("UTF-8"))).toString();
//THIS WORKED
return String.valueOf(base64Encode(pbeCipher.doFinal(encrypt_this.getBytes("UTF-8"))));
}//end of encrypt()
valueOf(char[])chứ không phải valueOf(Object). Các hành vi của valueOf(char[])là khác nhau đáng kể để char[].toString(). Nhưng dù bằng cách nào, câu trả lời này không phải là apropos bởi vì bạn đang gọi một tình trạng quá tải khác với câu hỏi mà bạn hỏi.
Dưới đây cho thấy việc triển khai cho java.lang.String.valueOf như được mô tả trong nguồn cho jdk8u25. Vì vậy, theo nhận xét của tôi, không có sự khác biệt. Nó gọi "Object.toString". Đối với các kiểu nguyên thủy, nó bọc nó ở dạng đối tượng và gọi "toString" trên nó.
Xem bên dưới:
/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public static String valueOf(char data[]) {
return new String(data);
}
public static String valueOf(char data[], int offset, int count) {
return new String(data, offset, count);
}
public static String copyValueOf(char data[], int offset, int count) {
return new String(data, offset, count);
}
public static String copyValueOf(char data[]) {
return new String(data);
}
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
public static String valueOf(char c) {
char data[] = {c};
return new String(data, true);
}
public static String valueOf(int i) {
return Integer.toString(i);
}
public static String valueOf(long l) {
return Long.toString(l);
}
public static String valueOf(float f) {
return Float.toString(f);
}
public static String valueOf(double d) {
return Double.toString(d);
}
String.valueOfđược sử dụng. Đối với các đối tượng ghi đè lênString, tôi nghĩ String.valueOf có thể gọi điều đó thay thế. Không chắc chắn về phần đó mặc dù.