ใน Java มีความแตกต่างระหว่างString.valueOf(Object)และObject.toString()อย่างไร มีการกำหนดรหัสเฉพาะสำหรับสิ่งเหล่านี้หรือไม่?
nullก่อน
ใน Java มีความแตกต่างระหว่างString.valueOf(Object)และObject.toString()อย่างไร มีการกำหนดรหัสเฉพาะสำหรับสิ่งเหล่านี้หรือไม่?
nullก่อน
คำตอบ:
ตามเอกสาร Java , String.valueOf()ผลตอบแทน:
ถ้าอาร์กิวเมนต์เป็น
nullสตริงเท่ากับ"null"; มิฉะนั้นมูลค่าของobj.toString()จะถูกส่งกลับ
ดังนั้นจึงไม่ควรมีความแตกต่างจริงๆยกเว้นการเรียกใช้เมธอดเพิ่มเติม
นอกจากนี้ในกรณีของObject#toStringถ้าอินสแตนซ์nullที่NullPointerExceptionจะถูกโยนเพื่อให้เนื้อหามันน้อยปลอดภัย
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)ได้ว่าเป็น NPE ใช้ได้เฉพาะกับวัตถุที่เป็นโมฆะ
String.valueOf(null)จริงจะช่วยแก้ปัญหาให้กับvalueOf(char[])การโอเวอร์โหลด นี้เป็นเพราะเป็นประเภทที่เฉพาะเจาะจงมากขึ้นกว่าchar[] Object
ความแตกต่างระหว่าง String.valueOf (Object) และ Object.toString () คือ:
1) ถ้าสตริงเป็นโมฆะ
String.valueOf(Object)จะกลับมาnullในขณะที่Object::toString()จะโยนข้อยกเว้นตัวชี้ว่าง
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) ลายเซ็น:
วิธี valueOf () ของคลาส String เป็นแบบคงที่ ในขณะที่วิธี toString () ของคลาส String ไม่คงที่
ลายเซ็นหรือไวยากรณ์ของวิธี valueOf () ของสตริงได้รับด้านล่าง:
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)
ลายเซ็นหรือไวยากรณ์ของtoString()วิธีการของสตริงได้รับด้านล่าง:
public String toString()
ใน Java มีความแตกต่างระหว่าง String.valueOf (Object) และ Object.toString () หรือไม่
ใช่. (และอื่น ๆ อีกมากมายหากคุณคิดว่าเกินกำลัง!)
ตามที่javadocอธิบายString.valueOf((Object) null)จะถือว่าเป็นกรณีพิเศษโดยvalueOfวิธีการและค่า"null"จะถูกส่งกลับ ในทางตรงกันข้ามnull.toString()จะให้ NPE แก่คุณ
แต่กลับกลายเป็นว่าString.valueOf(null)(โปรดสังเกตความแตกต่าง!) ไม่ให้ NPE ... แม้จะ Javadoc คำอธิบายคลุมเครือ:
มีจำนวนเกินของมีString.valueOfมีสองที่มีความเกี่ยวข้องที่นี่ แต่: และString.valueOf(Object)String.valueOf(char[])
ในนิพจน์String.valueOf(null)โอเวอร์โหลดทั้งสองแบบนั้นใช้ได้เนื่องจากการnullกำหนดเข้ากันได้กับประเภทการอ้างอิงใด ๆ
เมื่อมีโอเวอร์โหลดที่เกี่ยวข้องตั้งแต่สองตัวขึ้นไป JLS จะบอกว่ามีการเลือกโอเวอร์โหลดสำหรับประเภทอาร์กิวเมนต์ที่เฉพาะเจาะจงที่สุด
เนื่องจากchar[]เป็นชนิดย่อยของObjectมันเป็นเฉพาะเจาะจงมากขึ้น
ดังนั้นจึงString.valueOf(char[])เรียกว่าโอเวอร์โหลด
String.valueOf(char[])พ่น NPE หากอาร์กิวเมนต์เป็นอาร์เรย์ว่าง ต่างจากที่String.valueOf(Object)ไม่nullถือเป็นกรณีพิเศษ
(คุณสามารถยืนยันได้โดยใช้javap -cเพื่อตรวจสอบรหัสของวิธีการที่มีการString.valueOf(null)โทรสังเกตการโอเวอร์โหลดที่ใช้สำหรับการโทร)
อีกตัวอย่างหนึ่งแสดงให้เห็นถึงความแตกต่างของการvalueOf(char[])โอเวอร์โหลดที่ชัดเจนยิ่งขึ้น:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
มีการกำหนดรหัสเฉพาะสำหรับสิ่งเหล่านี้หรือไม่?
เลขที่
ใช้สิ่งที่เคยเหมาะสมที่สุดกับข้อกำหนดของบริบทที่คุณกำลังใช้ (คุณต้องการการจัดรูปแบบเพื่อใช้งานได้nullหรือไม่?)
หมายเหตุ: นั่นไม่ใช่หลักการเขียนโค้ด มันเป็นเพียงการเขียนโปรแกรมสามัญสำนึก สิ่งสำคัญกว่าคือรหัสของคุณจะถูกต้องมากกว่าที่จะเป็นไปตามแบบแผนโวหารหรือหลักปฏิบัติที่ดีที่สุด
ความเห็นส่วนตัว:
นักพัฒนาบางรายได้รับ (IMO) นิสัยที่ไม่ดีในการ "ปกป้อง" จากค่าว่าง คุณจะเห็นการทดสอบจำนวนมากสำหรับค่าว่างและถือว่าค่าว่างเป็นกรณีพิเศษ แนวคิดนี้ดูเหมือนจะป้องกันไม่ให้ NPE เกิดขึ้น
ฉันคิดว่านี่เป็นความคิดที่ไม่ดี. โดยเฉพาะอย่างยิ่งฉันคิดว่ามันเป็นความคิดที่ไม่ดีถ้าสิ่งที่คุณทำเมื่อคุณพบnullคือการพยายาม "ทำให้ดี" ... โดยไม่พิจารณาว่าทำไมถึงมีสิ่งnullนั้น
โดยทั่วไปแล้วจะเป็นการดีกว่าที่จะหลีกเลี่ยงการnullอยู่ที่นั่นตั้งแต่แรก ... เว้นแต่ว่าจะnullมีความหมายที่เฉพาะเจาะจงมากในแอปพลิเคชันหรือการออกแบบ API ของคุณ ดังนั้นแทนที่จะหลีกเลี่ยง NPE ที่มีการเข้ารหัสป้องกันจำนวนมากจะเป็นการดีกว่าที่จะปล่อยให้ NPE เกิดขึ้นจากนั้นติดตามและแก้ไขแหล่งที่มาของสิ่งที่ไม่คาดคิดnullที่ทำให้เกิด NPE
สิ่งนี้ใช้ที่นี่ได้อย่างไร?
ถ้าลองคิดดูการใช้String.valueOf(obj) อาจเป็นวิธี "สร้างความดี" ที่จะหลีกเลี่ยง. ถ้ามันเป็นที่ไม่คาดคิดสำหรับการobjที่จะเป็นในบริบทที่มันจะดีกว่าที่จะใช้nullobj.toString()
คำตอบอื่น ๆ กล่าวถึงส่วนใหญ่แล้ว แต่ฉันแค่เพิ่มเพื่อความสมบูรณ์:
.toString()เนื่องจากไม่ใช่การนำไปใช้Object-class ดังนั้นจึงString.valueOfสามารถใช้ได้เท่านั้นString.valueOfจะเปลี่ยนวัตถุที่กำหนดซึ่งเป็นnullString "null"ในขณะที่.toString()จะโยนไฟล์NullPointerException.String.valueOfโดยค่าเริ่มต้นเมื่อString s = "" + (...);มีการใช้สิ่งที่ต้องการ ซึ่งเป็นสาเหตุที่Object t = null; String s = "" + t;จะส่งผลให้ String "null"ไม่ใช่ใน NPE StringBuilder.appendไม่ใช่String.valueOf. ดังนั้นอย่าสนใจสิ่งที่ฉันพูดที่นี่นอกเหนือจากนั้นนี่เป็นกรณีการใช้งานที่String.valueOfและ.toString()มีผลลัพธ์ที่แตกต่างกัน:
สมมติว่าเรามีวิธีการทั่วไปดังนี้:
public static <T> T test(){
String str = "test";
return (T) str;
}
และเราจะเรียกมันด้วยIntegerประเภทดังนี้: Main.<Integer>test().
เมื่อเราสร้าง String โดยString.valueOfใช้งานได้ดี:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
สิ่งนี้จะส่งออกtestไปยัง STDOUT
ด้วย.toString()แต่มันจะไม่ทำงาน:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
ซึ่งจะส่งผลให้เกิดข้อผิดพลาดต่อไปนี้:
java.lang.ClassCastException:java.lang.Stringไม่สามารถส่งคลาสไปยังคลาสได้java.lang.Integer
สำหรับเหตุผลนั้นฉันสามารถอ้างถึงคำถามที่แยกออกมานี้และคำตอบของคำถามนั้นได้ อย่างไรก็ตามในระยะสั้น:
.toString()ครั้งแรกจะรวบรวมและประเมินวัตถุที่โยนไปT(ซึ่งเป็นStringไปIntegerโยนในกรณีนี้) ClassCastExceptionจะส่งผลให้String.valueOfมันจะเห็นทั่วไปTเป็นในระหว่างการรวบรวมและไม่ได้ดูแลเกี่ยวกับเรื่องนี้เป็นObject Integerดังนั้นมันจะส่งObjectไปยังObject(ซึ่งคอมไพเลอร์ก็เพิกเฉย) จากนั้นก็จะใช้งานString.valueOf(Object)ได้ผลStringตามที่คาดไว้ ดังนั้นแม้ว่าString.valueOf(Object)จะดำเนินการ.toString()กับพารามิเตอร์ภายในเราได้ข้ามการแคสต์ไปแล้วและถือว่าเป็นเช่นObjectนั้นดังนั้นเราจึงหลีกเลี่ยงสิ่งClassCastExceptionที่เกิดขึ้นกับการใช้.toString().แค่คิดว่ามันควรค่าแก่การกล่าวถึงความแตกต่างเพิ่มเติมระหว่างString.valueOfและ.toString()ที่นี่เช่นกัน
("" + x)รวบรวมถึงString.valueOf(x)แต่สิ่งที่ซับซ้อนกว่านั้นก็ใช้ a StringBuffer(เรายังไม่มีStringBuilder)
String.valueOf(Object)และObject.toString()เป็นสิ่งเดียวกันอย่างแท้จริง
หากคุณดูการใช้งานString.valueOf (Object)คุณจะเห็นว่าString.valueOf(Object)โดยพื้นฐานแล้วเป็นเพียงการเรียกtoString()ใช้อ็อบเจ็กต์ที่เหมาะสมโดยไม่มีค่าว่าง:
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();
}
ความแตกต่างที่สำคัญที่สุดคือวิธีจัดการการอ้างอิง null String
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
เมื่ออาร์กิวเมนต์เป็นnullที่String.valueOfผลตอบแทน"null"แต่Object.toStringโยนNullPointerExceptionว่าเป็นความแตกต่างเพียง
มีอีกหนึ่งความแตกต่างที่สำคัญระหว่างสองวิธีคือเมื่อวัตถุที่เรากำลังแปลงเป็นอาร์เรย์
เมื่อคุณแปลงอาร์เรย์โดยใช้ Object.toString () คุณจะได้รับค่าขยะบางประเภท (@ ตามด้วยแฮชโค้ดของอาร์เรย์)
ในการรับ toString () ที่มนุษย์อ่านได้คุณต้องใช้ String.valueOf (char []); โปรดทราบว่าวิธีนี้ใช้ได้กับ Array ของ type char เท่านั้น ฉันอยากจะแนะนำให้ใช้ Arrays.toString (Object []) สำหรับการแปลงอาร์เรย์เป็น String
ความแตกต่างประการที่สองคือเมื่อวัตถุเป็นโมฆะ ValueOf () จะส่งคืน String "null" ในขณะที่ toString () จะส่งกลับข้อยกเว้นของตัวชี้ค่าว่าง
ฉันไม่สามารถบอกได้อย่างชัดเจนว่าความแตกต่างคืออะไร แต่ดูเหมือนจะมีความแตกต่างเมื่อทำงานในระดับไบต์ ในสถานการณ์จำลองการเข้ารหัสต่อไปนี้ Object.toString () สร้างค่าที่ไม่สามารถถอดรหัสได้ในขณะที่ String.valueOf () ทำงานตามที่ตั้งใจไว้ ...
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[]) valueOf(Object)ลักษณะการทำงานของอย่างมีนัยสำคัญที่แตกต่างกันไปvalueOf(char[]) char[].toString()แต่ไม่ว่าจะด้วยวิธีใดคำตอบนี้ไม่ใช่aproposเพราะคุณกำลังเรียกโอเวอร์โหลดที่แตกต่างจากคำถามที่ถามถึง
และในกรณีส่วนใหญ่ควรส่งคืน NPE มากกว่าค่า "null"
ด้านล่างแสดงการใช้งานสำหรับ java.lang.String.valueOf ตามที่อธิบายไว้ในซอร์สสำหรับ jdk8u25 ตามความคิดเห็นของฉันไม่มีความแตกต่าง เรียกว่า "Object.toString" สำหรับประเภทดั้งเดิมจะรวมไว้ในรูปแบบวัตถุและเรียก "toString"
ดูด้านล่าง:
/*
* 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ถูกนำมาใช้ สำหรับวัตถุที่แทนที่ toString ฉันคิดว่า String.valueOf อาจเรียกสิ่งนั้นแทน ไม่แน่ใจเกี่ยวกับส่วนนั้นว่า