เหตุใดจึงไม่สามารถส่ง Integer เป็น String ใน java ได้


96

ฉันพบข้อยกเว้นแปลก ๆ :

java.lang.ClassCastException: java.lang.Integer 
 cannot be cast to java.lang.String

จะเป็นไปได้อย่างไร? แต่ละออบเจ็กต์สามารถถูกโยนเป็น String ได้ใช่หรือไม่?

รหัสคือ:

String myString = (String) myIntegerObject;

ขอบคุณ.


11
"แต่ละออบเจ็กต์สามารถถูกโยนเป็น String" - นี่ไม่ถูกต้อง แต่ทุกออบเจ็กต์มีtoString()วิธีการที่จะแปลงเป็นสตริง ตามที่หลาย ๆ คำตอบชี้ให้เห็นนั่นคือสิ่งที่คุณควรใช้ (สำหรับวัตถุบางอย่างtoString()ไม่ได้ส่งคืนสตริงที่มีประโยชน์มากนัก แต่สำหรับIntegerมันอาจจะทำตามที่คุณต้องการ)
Ted Hopp

2
""+myIntegerObjectยังใช้งานได้ :)
Salman von Abbas

1
ในกรณีของฉันข้อผิดพลาดนี้ได้รับการรายงานว่าเป็นความผิด ... ฉันกำลังใช้Integer.toString(IntegerObject)และมันทำให้ฉันเกิดข้อผิดพลาดนี้ แต่ก็พอใจกับIntegerObject.toString()... และใช่นั่นคือจำนวนเต็มและฉันได้รับข้อผิดพลาดนี้จริงๆ ...
Andrew

เกาที่String.valueOf()ใช้งานได้จริงเท่านั้น...
แอนดรู

คำตอบ:


157

เหตุใดจึงเป็นไปไม่ได้:

เนื่องจาก String และ Integer ไม่ได้อยู่ในลำดับชั้นของ Object เดียวกัน

      Object
     /      \
    /        \
String     Integer

การคัดเลือกนักแสดงที่คุณกำลังพยายามจะใช้งานได้ก็ต่อเมื่ออยู่ในลำดับชั้นเดียวกันเท่านั้นเช่น

      Object
     /
    /
   A
  /
 /
B

ในกรณีนี้(A) objBหรือ(Object) objBหรือ(Object) objAจะทำงาน

ดังนั้นตามที่คนอื่น ๆ ได้กล่าวไปแล้วในการแปลงจำนวนเต็มเป็นการใช้สตริง:

String.valueOf(integer)หรือInteger.toString(integer)สำหรับดั้งเดิม

หรือ

Integer.toString() สำหรับวัตถุ


แล้ว (A) objA, (B) objB และ (B) objA ล่ะ?
ซูอดีต

@ su-ex (B) objAจะไม่ทำงาน (A) objAและ(B) objBจะทำงาน
Bhushan

ขออภัยคุณพูดถูกสิ่งนี้ทำให้ ClassCastException อีกสองคนค่อนข้างไร้ประโยชน์ แต่จะได้ผลแน่นอน
ซูอดีต

45

ไม่ใช่IntegerและStringเป็นประเภทต่างๆ ในการแปลงจำนวนเต็มเป็นสตริงให้ใช้: String.valueOf(integer)หรือInteger.toString(integer)สำหรับดั้งเดิมหรือInteger.toString()สำหรับอ็อบเจ็กต์


1
@Ted Hopp - อันไหน? ถ้าเป็นแบบดั้งเดิมให้ใช้สองตัวแรกถ้าเป็นอ็อบเจ็กต์ Integer ให้ใช้อันที่สาม
Petar Minchev

อ๊ะ. ฉันไม่เห็นวลีสุดท้ายของคำตอบของคุณ ฉันกำลังลบความคิดเห็นและโหวตคำตอบนี้
Ted Hopp

1
ปัญหาที่คล้ายกัน (แต่ไม่ซ้ำกัน): ไม่สามารถแคสต์ 'int' เป็นสตริงได้เนื่องจาก 'int' ไม่ใช่อ็อบเจ็กต์ซึ่งน้อยกว่ามากในลำดับชั้นของสตริง
Kelly S. French

20

สำหรับintประเภทการใช้งาน:

int myInteger = 1;
String myString = Integer.toString(myInteger);

สำหรับIntegerประเภทการใช้งาน:

Integer myIntegerObject = new Integer(1);
String myString = myIntegerObject.toString();

สิ่งนี้บังคับให้ทำการแกะกล่องโดยไม่จำเป็น
Ted Hopp

@Ted Hopp ดูการแก้ไขของฉันเพื่อชี้แจงว่าเมื่อใดควรใช้toString()วิธีการแต่ละประเภท
DRiFTy

ฉันคิดว่าบรรทัดสุดท้ายน่าจะเป็นString myString = myIntegerObject.toString();
Ted Hopp

6

ไม่ได้วัตถุทุกชิ้นสามารถโยนเป็นjava.lang.Objectไฟล์String. หากคุณต้องการแสดงสตริงของวัตถุใด ๆ คุณต้องเรียกใช้toString()เมธอด สิ่งนี้ไม่เหมือนกับการหล่อวัตถุเป็น String


5

ออบเจ็กต์สามารถแปลงเป็นสตริงได้โดยใช้toString()วิธีการ:

String myString = myIntegerObject.toString();

ไม่มีกฎดังกล่าวเกี่ยวกับการเป็นหล่อ สำหรับการแคสต์ไปใช้งานจริงวัตถุจะต้องเป็นประเภทที่คุณกำลังหล่อ


5

คุณไม่สามารถแคสต์สิ่งStringที่ไม่ใช่ไฟล์String. คุณควรใช้อย่างใดอย่างหนึ่ง:

"" + myInt;

หรือ:

Integer.toString(myInt);

หรือ:

String.valueOf(myInt);

ฉันชอบรูปแบบที่สองมากกว่า แต่ฉันคิดว่ามันเป็นทางเลือกส่วนตัว

แก้ไขตกลงนี่คือเหตุผลที่ฉันชอบรูปแบบที่สอง รูปแบบแรกเมื่อคอมไพล์สามารถสร้างอินสแตนซ์ a StringBuffer(ใน Java 1.4) หรือ a StringBuilderใน 1.5; อีกสิ่งหนึ่งที่ต้องเก็บขยะ คอมไพเลอร์ไม่ได้ปรับให้เหมาะสมเท่าที่ฉันสามารถบอกได้ รูปแบบที่สองยังมีอะนาล็อกInteger.toString(myInt, radix)ซึ่งช่วยให้คุณระบุได้ว่าคุณต้องการเลขฐานสิบหกฐานแปดและอื่น ๆ หรือไม่หากคุณต้องการให้รหัสของคุณมีความสอดคล้องกัน (ฉันเดาว่ามีความสวยงามอย่างแท้จริง) รูปแบบที่สองสามารถใช้ในที่ต่างๆได้มากขึ้น

แก้ไข 2ฉันคิดว่าคุณหมายความว่าจำนวนเต็มของคุณเป็นintและไม่ใช่Integer. หากมีอยู่แล้วIntegerเพียงแค่ใช้toString()มันและเสร็จสิ้น


OP เริ่มต้นด้วยวัตถุจำนวนเต็ม myIntegerObject.toString()มันมีประสิทธิภาพมากขึ้นที่จะทำ
Ted Hopp


2

การแคสต์แตกต่างจากการแปลงใน Java คือใช้คำศัพท์ที่ไม่เป็นทางการ

การแคสต์ออบเจ็กต์หมายความว่าออบเจ็กต์นั้นเป็นสิ่งที่คุณกำลังส่งไปอยู่แล้วและคุณแค่บอกคอมไพเลอร์เกี่ยวกับมัน ตัวอย่างเช่นถ้าฉันมีFooข้อมูลอ้างอิงที่ฉันรู้ว่าเป็นFooSubclassอินสแตนซ์ก็(FooSubclass)Fooบอกคอมไพเลอร์ว่า "อย่าเปลี่ยนอินสแตนซ์แค่รู้ว่ามันเป็นFooSubclass .

ในทางตรงกันข้ามการIntegerเป็นไม่Stringแม้ว่า (ตามที่คุณชี้ให้เห็น) มีวิธีการในการรับที่แสดงถึงString Integerเนื่องจากไม่มีตัวอย่างใดที่Integerสามารถเป็นได้Stringคุณจึงไม่สามารถส่งIntegerไปStringได้


1

ในกรณีของคุณไม่จำเป็นต้องแคสต์คุณต้องโทรไปที่String ()

Integer i = 33;
String s = i.toString();
//or
s = String.valueOf(i);
//or
s = "" + i;

การคัดเลือกนักแสดง. มันทำงานอย่างไร?

ให้:

class A {}
class B extends A {}

(A)
  |
(B)

B b = new B(); //no cast
A a = b;  //upcast with no explicit cast
a = (A)b; //upcast with an explicit cast
b = (B)a; //downcast

A และ B ในโครงสร้างมรดกเดียวกันและเราสามารถทำได้:

a = new A();
b = (B)a;  // again downcast. Compiles but fails later, at runtime: java.lang.ClassCastException

คอมไพเลอร์ต้องอนุญาตสิ่งต่างๆที่อาจทำงานได้ในขณะรันไทม์ อย่างไรก็ตามหากคอมไพเลอร์รู้ 100% ว่าการแคสต์ไม่สามารถทำงานได้การคอมไพเลอร์จะล้มเหลว
ให้:

class A {}
class B1 extends A {}
class B2 extends A {}

        (ก)
      / \
(B1) (B2)

B1 b1 = new B1();
B2 b2 = (B2)b1; // B1 can't ever be a B2

ข้อผิดพลาด: ประเภทที่แปลงกลับไม่ได้ B1 และ B2 คอมไพเลอร์รู้ 100% ว่าการแคสต์ไม่สามารถทำงานได้ แต่คุณสามารถโกงคอมไพเลอร์ได้:

B2 b2 = (B2)(A)b1;

แต่อย่างไรก็ตามในรันไทม์:

ข้อยกเว้นในเธรด "main" java.lang.ClassCastException: B1 ไม่สามารถส่งเป็น B2

ในกรณีของคุณ:

          (วัตถุ)
            / \
(จำนวนเต็ม) (สตริง)

Integer i = 33;
//String s = (String)i; - compiler error
String s = (String)(Object)i;

ที่รันไทม์: ข้อยกเว้นในเธรด "main" java.lang.ClassCastException: java.lang.Integer ไม่สามารถส่งไปยัง java.lang.String


0

ใช้String.valueOf (จำนวนเต็ม)(จำนวนเต็ม)

ส่งคืนการแสดงสตริงของจำนวนเต็ม


ดังที่ Petar กล่าวไว้ข้างต้นนั่นควรจะเป็นString.valueOf(integer)
Urs Reupke

@UrsReupke: ขอบคุณจริงๆเมื่อฉันพยายามเพิ่มลิงค์ฉันเขียนผิด
RanRag

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.