ใน 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
ที่จะเป็นในบริบทที่มันจะดีกว่าที่จะใช้null
obj.toString()
คำตอบอื่น ๆ กล่าวถึงส่วนใหญ่แล้ว แต่ฉันแค่เพิ่มเพื่อความสมบูรณ์:
.toString()
เนื่องจากไม่ใช่การนำไปใช้Object
-class ดังนั้นจึงString.valueOf
สามารถใช้ได้เท่านั้นString.valueOf
จะเปลี่ยนวัตถุที่กำหนดซึ่งเป็นnull
String "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 อาจเรียกสิ่งนั้นแทน ไม่แน่ใจเกี่ยวกับส่วนนั้นว่า