Объяснение "ClassCastException" в Java

Я читал некоторые статьи, написанные на "ClassCastException", но я не мог получить хорошее представление об этом. Есть ли хорошая статья или то, что было бы кратким объяснением?

11 ответов


прямо из спецификаций API для ClassCastException:

брошенный, чтобы указать, что код попытка бросить объект в подкласс, к которому он не относится пример.

так, например, когда один пытается бросить Integer до String, String не является подклассом Integer, Так что ClassCastException будет брошен.

Object i = Integer.valueOf(42);
String s = (String)i;            // ClassCastException thrown here.

это действительно довольно просто: если вы пытаетесь типизировать объект класса A в объект класса B, и они несовместимы, вы получаете исключение класса cast.

давайте подумаем о коллекции классов.

class A {...}
class B extends A {...}
class C extends A {...}
  1. вы можете привести любую из этих вещей к объекту, потому что все классы Java наследуются от Object.
  2. вы можете бросить либо B, либо C В A, потому что они оба "виды" a
  3. вы можете привести ссылку на объект A К Б только если реальный объект является Б.
  4. вы не можете бросить B В C, даже если они оба A.

это исключение, которое возникает, если вы пытаетесь понизить класс, но на самом деле класс не такого типа.

рассмотрим эту наследственность:

Объект -> Животные -> Собаки

у вас может быть метод под названием:

 public void manipulate(Object o) {
     Dog d = (Dog) o;
 }

если вызывается с этим кодом:

 Animal a = new Animal();
 manipulate(a);

Он будет компилироваться нормально, но во время выполнения, вы получите ClassCastException потому что о на самом деле был животным, а не собакой.

в более поздних версиях Java вы получаете предупреждение компилятора, если вы не делаете:

 Dog d;
 if(o instanceof Dog) {
     d = (Dog) o;
 } else {
     //what you need to do if not
 }

Рассмотрим пример

class Animal {
    public void eat(String str) {
        System.out.println("Eating for grass");
    }
}

class Goat extends Animal {
    public void eat(String str) {
        System.out.println("blank");
    }
}

class Another extends Goat{
  public void eat(String str) {
        System.out.println("another");
  }
}

public class InheritanceSample {
    public static void main(String[] args) {
        Animal a = new Animal();
        Another t5 = (Another) new Goat();
    }
}

At Another t5 = (Another) new Goat() вы получаете ClassCastException потому что вы не можете создать экземпляр Another класс с помощью Goat.

Примечание: преобразование действует только в тех случаях, когда класс расширяет родительский класс и дочерний класс будет преобразован в своего родительского класса.

как бороться с ClassCastException:

  1. будьте осторожны при попытке привести объект класса в другой класс. Обеспечить, чтобы новый тип принадлежит к одному из родительских классов.
  2. вы можете предотвратить ClassCastException с помощью дженериков, поскольку дженерики обеспечивают проверку времени компиляции и могут использоваться для разработки приложений, безопасных для типов.

источник записки и остальное


вы понимаете концепцию кастинга? Литье-это процесс преобразования типов, который в Java очень распространен, потому что его статически типизированный язык. Некоторые примеры:

приведите строку " 1 " к int -> no problem

приведите строку " abc " к int -> вызывает ClassCastException

или подумайте о диаграмме классов с Animal.класс, пес.класс и кошка.класс!--2-->

Animal a = new Dog();
Dog d = (Dog) a; // No problem, the type animal can be casted to a dog, because its a dog.
Cat c = (Dog) a; // Raises class cast exception; you can't cast a dog to a cat.

вы пытаетесь рассматривать объект как экземпляр класса, что это не так. Это примерно аналогично попытке нажать педаль демпфера на гитаре (у пианино есть педали демпфера, у гитар нет).


исключение приведения класса создается Java при попытке приведения объекта одного типа данных к другому.

Java позволяет нам передавать переменные одного типа другому, пока кастинг происходит между совместимыми типами данных.

например, вы можете привести строку в качестве объекта, и аналогично объект, содержащий строковые значения, может быть приведен к строке.

пример

предположим, что у нас есть HashMap, который содержит ряд ArrayList объекты.

Если мы напишем такой код:

String obj = (String) hmp.get(key);

это вызовет исключение cast класса, потому что значение, возвращаемое методом get хэш-карты, будет списком массивов, но мы пытаемся привести его к строке. Это вызвало бы исключение.


очень хороший пример, который я могу дать вам для classcastException в Java, при использовании "Collection"

List list = new ArrayList();
list.add("Java");
list.add(new Integer(5));

for(Object obj:list) {
    String str = (String)obj;
}

этот код выше даст вам ClassCastException во время выполнения. Поскольку вы пытаетесь привести целое число к строке, это вызовет исключение.


вы можете лучше понять ClassCastException и кастинг, как только поймете, что JVM не может угадать неизвестное. Если b является экземпляром A, он имеет больше членов класса и методов в куче, чем A. JVM не может догадаться, как привести A к B, так как цель сопоставления больше, и JVM не будет знать, как заполнить дополнительные члены.

но если бы A был экземпляром B, это было бы возможно, потому что A является ссылкой на полный экземпляр B, поэтому отображение будет один на один.


исключение Java ClassCastException является исключением, которое может возникнуть при попытке неправильно преобразовать класс из одного типа в другой.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ClassCastExceptionExample {

  public ClassCastExceptionExample() {

    List list = new ArrayList();
    list.add("one");
    list.add("two");
    Iterator it = list.iterator();
    while (it.hasNext()) {
        // intentionally throw a ClassCastException by trying to cast a String to an
        // Integer (technically this is casting an Object to an Integer, where the Object 
        // is really a reference to a String:
        Integer i = (Integer)it.next();
    }
  }
 public static void main(String[] args) {
  new ClassCastExceptionExample();
 }
}

Если вы попытаетесь запустить эту программу Java, вы увидите, что она бросит следующее исключение ClassCastException:

Exception in thread "main" java.lang.ClassCastException: java.lang.String
at ClassCastExceptionExample  (ClassCastExceptionExample.java:15)
at ClassCastExceptionExample.main  (ClassCastExceptionExample.java:19)

причина, по которой здесь возникает исключение, заключается в том, что при создании объекта list объект, который я храню в списке, является строкой "one", но затем, когда я пытаюсь получить этот объект, я намеренно делаю ошибка в попытке привести его к целому числу. Поскольку строка не может быть непосредственно приведена к целому числу-целое число не является типом строки-создается исключение ClassCastException.


Если вы хотите сортировать объекты, но если класс не реализовал Comparable или Comparator, то вы получите ClassCastException Например

class Animal{
   int age;
   String type;

   public Animal(int age, String type){
      this.age = age;
      this.type = type;
   }
}
public class MainCls{
   public static void main(String[] args){
       Animal[] arr = {new Animal(2, "Her"), new Animal(3,"Car")};
       Arrays.sort(arr);
   }
}

выше main метод будет бросать ниже класса выполнения cast exception

исключение в потоке" main " java.ленг.ClassCastException: com.по умолчанию.Животное не может быть брошено на java.ленг.Сравнимый