Java lang classcastexception что это
Перейти к содержимому

Java lang classcastexception что это

  • автор:

Java lang classcastexception что это

Брошенный, чтобы указать, что код попытался бросить объект к подклассу, которого это не экземпляр. Например, следующий код генерирует a ClassCastException :

Object x = new Integer(0); System.out.println((String)x);

Сводка конструктора

Конструкции a ClassCastException без сообщения детали.

Конструкции a ClassCastException с указанным сообщением детали.

Сводка метода

Методы java.lang унаследованный от класса. Throwable

Методы java.lang унаследованный от класса. Объект

Деталь конструктора

ClassCastException
public ClassCastException()

Конструкции a ClassCastException без сообщения детали.

ClassCastException

Конструкции a ClassCastException с указанным сообщением детали.

Платформа Java™
Стандарт Эд. 7

Представьте ошибку или функцию
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE . Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.

6 Java исключений, которые преследуют новичков

Java-университет

6 Java исключений, которые преследуют новичков - 1

Время от времени я сталкиваюсь с разработчиками-новичками, которые застряли на понимании следующих простых исключений и мне приходиться все заново объяснять им. Скорей всего в подобной ситуации оказываются многие опытные Java разработчики, которые помогают новичкам справиться со следующими исключениями. Поэтому я решил написать эту статью и в будущем ссылаться на нее. Комментарии и добавления в список исключений приветствуются.

  1. NoClassDefFoundError : Это одно из тех исключений, которое сообщением Exception in thread “main“ NoClassDefFoundError часто приветствует новых разработчиков в мире Java программирования. Они пишут helloworld-программу, идут в командную строку и пишут “java“ — команду для выполнения и «БАМ»:-) Немного времени спустя новички поймут как исправить это исключение и увидят как выводиться их hello world. NoClassDefFoundError случается тогда, когда виртуальная машина Java (JVM) пытается получить доступ к классу во время исполнения и этот класс не находится, хотя тот же класс находился во время компиляции. Чаще всего это исключение случается при запуске Java программы через команду “java“ с неверным значением параметра classpath . [ Classpath – это параметр, который задается через командную строку или через переменную окружения, указывающий виртуальной Java машине или Java компилятору где искать классы или пакеты объявленные пользователем – прим. переводчика] Возможные причины исключения:
    • Класс недоступен в Classpath .
    • Часто скрипт, который исполняется при запуске операционной системы, изменяет значение переменной окружению classpath . Это можно проверить выполнив команду “ set ” в командной строке в Windows и посмотрев включено ли определение класса в значение classpath . При желании дальнейшее изучение этого исключения можно продолжить в блоге Javarevisited.
  2. ClassNotFoundException : Исключение ClassNotFoundException это еще одно исключение, из-за которого новичкам, только начинающим программировать на Java, снятся кошмары. Интересно что для среднего разработчика нужно некоторое время чтобы перестать путать ClassNotFoundException и NoClassDefFoundError между собой. И поэтому вопрос о разнице этих двух исключений остается одним из часто задаваемых на собеседовании на позицию junior Java разработчика.
    ClassNotFoundException случается когда JVM пытается загрузить определенный класс и не обнаруживает такого же в classpath . Обычно новички сталкиваются с этим в коде, который подключается к базе данных используя JDBC библиотеку. Пытаясь загрузить драйвер с помощью следующего кода Class.forName( “JDBCdriver”) . Хороший материал по ClassNotFoundException можно найти здесь. Так же рекомендуется ознакомиться и понять концепцию загрузчиков классов в Java чтобы эффективно справляться с этим исключением. Вы возможно захотите посмотреть следующую страницу о том как настроить classpath в окружениях Win/Unix. А так, как следует из документации Java, это исключение случается в следующих случаях:
    1. Когда пытаются загрузить класс используя метод Class.forName и файл .class не существует в classpath . Это самый частый случай из всех трех.
    2. Когда загрузчик класса пытается загрузить класс используя метод loadClass .
    3. Когда загрузчик класса пытается загрузить класс используя findSystemClass .
  3. NullPointerException : исключение NullPointerException понять легче и новички с ним справляются быстрее нежели с двумя предыдущими. В тоже время причину исключения очень легко найти так как приводится номер строки где оно случилось. В первую очередь исключение случается когда JVM пытается обратиться к null в том месте где должен был быть объект. Чаще всего это случается когда JVM пытается вызвать метод используя объект и оказывается что объект равен null . Другие случаи, как упоминается в документации Java, могут быть следующими:
    1. Получая доступ к или изменяя метод объекта, который равен null .
    2. Получая длину массива когда он равен null .
    3. Получая доступ к или меняя объекты, которые являются заключенными в массив, который равен null .

    Самый простой способ избежать этого исключения это добавить проверку на неравенство null (далее – проверка на null – прим. переводчика). Поэтому рано или поздно разработчик начинает это использовать и тогда проверки на null появляются везде. Интересно что использовать везде проверку на null не считается примером хорошего программирования. Основная причина почему проверка на null используется разработчиками это передавать объект null в случаи ошибки. В место этого пример хорошего программирования, который должен пропагандироваться программистами, это передавать пустой объект когда условие для главной/рабочей ветви программы не удовлетворяется. Это в свою очередь уменьшило бы количество проверок на null . Все-таки легче говорить нежели применять это на практике.:)

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

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

    Давайте рассмотрим некоторые сценарии, которые приводят к возникновению этого исключения, и то, как мы можем их избежать.

    2. Явный кастинг​

    Для наших следующих экспериментов рассмотрим следующие классы:

     public interface Animal    String getName();   > 
     public class Mammal implements Animal    @Override   public String getName()    return "Mammal";   >   > 
     public class Amphibian implements Animal    @Override   public String getName()    return "Amphibian";   >   > 
     public class Frog extends Amphibian    @Override   public String getName()    return super.getName() + ": Frog";   >   > 

    2.1. Классы кастинга​

    На сегодняшний день наиболее распространенным сценарием возникновения ClassCastException является явное приведение к несовместимому типу.

    Например, давайте попробуем привести лягушку к млекопитающему :

     Frog frog = new Frog();   Mammal mammal = (Mammal) frog; 

    Мы могли бы ожидать здесь ClassCastException , но на самом деле мы получаем ошибку компиляции: «несовместимые типы: лягушка не может быть преобразована в млекопитающее». Однако ситуация меняется, когда мы используем общий супертип:

     Animal animal = new Frog();   Mammal mammal = (Mammal) animal; 

    Теперь мы получаем ClassCastException из второй строки:

     Exception in thread "main" java.lang.ClassCastException: class Frog cannot be cast to class Mammal (Frog and Mammal are in unnamed module of loader 'app')  at Main.main(Main.java:9) 

    Проверенное нисходящее приведение к Mammal несовместимо со ссылкой Frog, потому что Frog не является подтипом Mammal . В этом случае компилятор нам помочь не сможет, так как переменная Animal может содержать ссылку совместимого типа.

    Интересно отметить, что ошибка компиляции возникает только тогда, когда мы пытаемся выполнить приведение к однозначно несовместимому классу. То же самое не верно для интерфейсов, потому что Java поддерживает множественное наследование интерфейсов, но только одиночное наследование для классов. Таким образом, компилятор не может определить, реализует ли ссылочный тип конкретный интерфейс или нет. Приведем пример:

     Animal animal = new Frog();   Serializable serial = (Serializable) animal; 

    Мы получаем ClassCastException во второй строке вместо ошибки компиляции:

     Exception in thread "main" java.lang.ClassCastException: class Frog cannot be cast to class java.io.Serializable (Frog is in unnamed module of loader 'app'; java.io.Serializable is in module java.base of loader 'bootstrap')  at Main.main(Main.java:11) 

    2.2. Приведение массивов​

    Мы видели, как классы обрабатывают приведение типов, теперь давайте посмотрим на массивы. Приведение массивов работает так же, как приведение классов. Однако нас может запутать автоупаковка и продвижение шрифта или их отсутствие.

    Итак, давайте посмотрим, что происходит с примитивными массивами, когда мы пытаемся выполнить следующее приведение:

     Object primitives = new int[1];   Integer[] integers = (Integer[]) primitives; 

    Вторая строка генерирует исключение ClassCastException , так как автоупаковка не работает для массивов.

    Как насчет продвижения типа? Давайте попробуем следующее:

     Object primitives = new int[1];   long[] longs = (long[]) primitives; 

    Мы также получаем ClassCastException , потому что повышение типа не работает для целых массивов.

    2.3. Безопасный кастинг​

    В случае явного приведения настоятельно рекомендуется проверить совместимость типов перед попыткой приведения с использованием instanceof .

    Давайте посмотрим на пример безопасного приведения:

     Mammal mammal;   if (animal instanceof Mammal)    mammal = (Mammal) animal;   > else    // handle exceptional case   > 

    3. Загрязнение кучи​

    В соответствии со спецификацией Java : « Загрязнение кучи может произойти только в том случае, если программа выполнила какую-либо операцию с необработанным типом, которая привела бы к непроверенному предупреждению во время компиляции».

    Для нашего эксперимента рассмотрим следующий универсальный класс:

     public static class Box    private T content;    public T getContent()    return content;   >    public void setContent(T content)    this.content = content;   >   > 

    Теперь попробуем загрязнить кучу следующим образом:

     BoxLong> originalBox = new Box>();   Box raw = originalBox;  raw.setContent(2.5);   BoxLong> bound = (BoxLong>) raw;   Long content = bound.getContent(); 

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

    4. Общие типы​

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

    Рассмотрим следующий общий метод:

     public static T> T convertInstanceOfObject(Object o)    try    return (T) o;   > catch (ClassCastException e)    return null;   >   > 

    А теперь назовем это:

     String shouldBeNull = convertInstanceOfObject(123); 

    На первый взгляд, мы можем разумно ожидать, что из блока catch будет возвращена нулевая ссылка. Однако во время выполнения из-за стирания типа параметр приводится к Object вместо String . Таким образом, перед компилятором стоит задача присвоить Integer String , что вызовет исключение ClassCastException.

    5. Вывод​

    В этой статье мы рассмотрели ряд распространенных сценариев неуместного кастинга.

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

    Код, использованный в этой статье, можно найти на GitHub .

    • 1. Обзор
    • 2. Явный кастинг
      • 2.1. Классы кастинга
      • 2.2. Приведение массивов
      • 2.3. Безопасный кастинг

      java.lang.ClassCastException на том же самом классе

      Исключение java . lang . ClassCastException возникает при попытке приведения объекта к подклассу, экземпляром которого он не является.

      public class Main
      public static void main ( String [ ] args ) < Object obj = new java . util . Date ( ) ; Integer int1 = ( Integer ) obj ;

      Этот код при выполнении бросит исключение:

      Exception in thread «main» java . lang . ClassCastException : java . util . Date cannot be cast to java . lang . Integer

      at Main . main ( Main . java : 5 )

      Но бывает такая странная ситуация, когда исключение возникает при попытке преобразовать к классу, которым объект собственно и является. Например:

      java . lang . ClassCastException : org . postgresql . util . PGInterval cannot be cast to org . postgresql . util . PGInterval

      На первый взгляд кажется, что это абсурд. Как это так, что нельзя привести класс к самому себе? Но такая ситуация вполне возможна. Она может возникнуть в случаях, когда у вас есть два одинаковых класса, но загруженных разными ClassLoader -ами. А это возможно, например, при разработке под WEB (J2EE, Spring Framework и т. д.). У меня такая ситуация возникла в случае, когда jar-ник с драйвером PostgreSQL был подключен два раза: один раз в war-файле, второй раз он был в каталоге lib у Apache Tomcat. По идее драйвер должен лежать в каталоге lib. Но проект начинал свой путь ещё до меня. Я решил в этом случае не использовать org . postgresql . util . PGInterval напрямую, а использовать Object и обращаться к методам через Reflection.

      Получилось примерно вот так:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *