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.

user710818
źródło
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.

Bhushan
źródło
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.

Petar Minchev
źródło
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();
DRiFTy
źródło
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.

andri
źródło
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.

millimoose
źródło
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.

Jonathan
źródło
OP zaczyna się od obiektu Integer. O wiele bardziej wydajne jest po prostu zrobienie tego myIntegerObject.toString().
Ted Hopp
4

Powinieneś wywołać myIntegerObject.toString (), jeśli chcesz reprezentować ciąg.

Savino Sguera
źródło
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

yshavit
źródło
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

Dmitry Sokolyuk
źródło
0

Użyj String.valueOf (integer) .

Zwraca łańcuch reprezentujący liczbę całkowitą.

RanRag
źródło
Jak mówi Petar powyżej, powinno to byćString.valueOf(integer)
Urs Reupke
@UrsReupke: dzięki, właściwie, kiedy próbowałem dodać link, napisałem go ponownie źle.
RanRag
0

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

String myString = myIntegerObject.toString();
A. Alem 11
źródło