Dlaczego nie można rzutować liczby całkowitej na ciąg znaków w Javie?


95

Znalazłem dziwny wyjątek:

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

Jak to możliwe? Każdy obiekt może być rzutowany na String, prawda?

Kod to:

String myString = (String) myIntegerObject;

Dzięki.


11
„Każdy obiekt można rzutować na łańcuch” - to jest błędne. Przeciwnie, każdy obiekt ma toString()metodę, która przekształci go w String. Jak wskazuje kilka odpowiedzi, właśnie tego powinieneś użyć. (W przypadku niektórych obiektów, toString()nie zwraca bardzo przydatnych ciąg, ale za Integerto prawdopodobnie robi dokładnie to, co chcesz.)
Ted Hopp

2
""+myIntegerObjectteż działa :)
Salman von Abbas

1
W moim przypadku ten błąd został zgłoszony jako błąd ... Używałem Integer.toString(IntegerObject)i dał mi ten błąd, ale jest zadowolony z IntegerObject.toString()... I tak, to naprawdę jest liczba całkowita i naprawdę dostałem ten błąd ...
Andrew

Zresztą, tylko String.valueOf()faktycznie działa ...
Andrew

Odpowiedzi:


155

Dlaczego nie jest to możliwe:

Ponieważ ciąg i liczba całkowita nie znajdują się w tej samej hierarchii obiektów.

      Object
     /      \
    /        \
String     Integer

Casting, który próbujesz, działa tylko wtedy, gdy są w tej samej hierarchii, np

      Object
     /
    /
   A
  /
 /
B

W takim przypadku (A) objBlub (Object) objBlub (Object) objAzadziała.

Dlatego, jak już wspominali inni, aby przekonwertować liczbę całkowitą na łańcuch, użyj:

String.valueOf(integer)lub Integer.toString(integer)dla prymitywnych,

lub

Integer.toString() dla obiektu.


A co z (A) objA, (B) objB i (B) objA?
su-ex

@ su-ex (B) objAnie będzie działać. (A) objAi (B) objBbędzie działać.
Bhushan

Przepraszamy, masz rację, to daje ClassCastException. Pozostałe dwa są zupełnie bezużyteczne, ale oczywiście będą działać.
su-ex

45

Nie, Integeri Stringsą to różne typy. Aby przekonwertować liczbę całkowitą na łańcuch, użyj:, String.valueOf(integer)lub Integer.toString(integer)dla prymitywu lub Integer.toString()dla obiektu.


1
@Ted Hopp - który? Jeśli jest to prymityw, użyj dwóch pierwszych, jeśli jest to obiekt Integer, użyj trzeciego.
Petar Minchev

Ups. Nie widziałem ostatniej frazy twojej odpowiedzi. Usuwam swój komentarz i zagłosuję za tą odpowiedzią.
Ted Hopp

1
Podobny (ale nie zduplikowany) problem: „int” nie może być rzutowany na String, ponieważ „int” nie jest obiektem, a tym bardziej w hierarchii String.
Kelly S. French

20

Do inttypów użyj:

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

Do Integertypów użyj:

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

Wymusza to niepotrzebną operację rozpakowywania.
Ted Hopp

@Ted Hopp zobacz moje zmiany, aby wyjaśnić, kiedy należy użyć każdego rodzaju toString()metody
DRiFTy

Myślę, że ostatnia linia powinna byćString myString = myIntegerObject.toString();
Ted Hopp

6

Nie. Każdy obiekt można rzucić na plik java.lang.Object, a nie String. Jeśli chcesz, aby dowolny obiekt był reprezentacją łańcuchową, musisz wywołać toString()metodę; to nie to samo, co rzutowanie obiektu na String.


5

Obiekty można przekonwertować na ciąg przy pomocy toString()metody:

String myString = myIntegerObject.toString();

Nie ma takiej zasady dotyczącej castingu . Aby rzutowanie działało, obiekt musi być typu, do którego rzutujesz.


5

Nie możesz bezpośrednio rzutować niczego do pliku, Stringktóry nie jest String. Powinieneś użyć:

"" + myInt;

lub:

Integer.toString(myInt);

lub:

String.valueOf(myInt);

Wolę drugą formę, ale myślę, że to osobisty wybór.

Edytuj OK, oto dlaczego wolę drugą formę. Pierwsza forma, po skompilowaniu, mogłaby utworzyć instancję a StringBuffer(w Javie 1.4) lub a StringBuilderw 1.5; jeszcze jedna rzecz do zebrania śmieci. Kompilator nie optymalizuje tego, o ile mogę powiedzieć. Druga forma również ma analogię, Integer.toString(myInt, radix)która pozwala określić, czy chcesz mieć szesnastkowy, ósemkowy itp. Jeśli chcesz zachować spójność w swoim kodzie (myślę, że czysto estetycznie), druga forma może być używana w większej liczbie miejsc.

Edycja 2 Zakładałem, że masz na myśli, że twoja liczba całkowita to inta nie Integer. Jeśli to już jest Integer, po prostu użyj toString()na nim i gotowe.


OP zaczyna się od obiektu Integer. O wiele bardziej wydajne jest po prostu zrobienie tego myIntegerObject.toString().
Ted Hopp


2

Casting różni się od konwersji w Javie, aby używać nieformalnej terminologii.

Rzutowanie obiektu oznacza, że ​​obiekt już jest tym, do czego go rzutujesz i po prostu mówisz o tym kompilatorowi. Na przykład, jeśli mam Fooodniesienie, o którym wiem, że jest FooSubclassprzykładem, to(FooSubclass)Foo powie kompilatorowi: „Nie zmieniaj instancji, po prostu wiedz, że jest to instancja FooSubclass.

Z drugiej strony an nieInteger jest a , chociaż (jak zauważyłeś) istnieją metody uzyskiwania a, które reprezentuje . Ponieważ żadna instancja nie może nigdy być a , nie można przesyłać do .StringStringIntegerIntegerStringIntegerString


1

W twoim przypadku nie potrzebujesz rzutowania, potrzebujesz wywołania toString ().

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

Odlew. Jak to działa?

Dany:

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 i B w tym samym drzewie dziedziczenia i możemy to:

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

Kompilator musi zezwalać na rzeczy, które mogą działać w czasie wykonywania. Jeśli jednak kompilator wie ze 100%, że rzutowanie nie może działać, kompilacja się nie powiedzie.
Dany:

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

        (A)
      / \
(B1) (B2)

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

Błąd: nieodwracalne typy B1 i B2. Kompilator wie ze 100%, że obsada nie może działać. Ale możesz oszukać kompilator:

B2 b2 = (B2)(A)b1;

ale tak czy inaczej w czasie wykonywania:

Wyjątek w wątku „main” java.lang.ClassCastException: B1 nie można rzutować na B2

w Twoim przypadku:

          (Obiekt)
            / \
(Liczba całkowita) (Ciąg)

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

w czasie wykonywania: wyjątek w wątku „main” java.lang.ClassCastException: nie można przesłać java.lang.Integer do java.lang.String



0

Zamiast tego użyj .toString, jak poniżej:

String myString = myIntegerObject.toString();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.