- How to fix java.lang.classcastexception cannot be cast to in Java — cause and solution
- Cause of java.lang.ClassCastException in Java
- Common source of java.lang.ClassCastException
- How to fix java.lang.ClassCastException in Java
- Hibernate HQL casting: java.lang.String cannot be cast to java.lang.Enum
- Solution 2
- Javi Pedrera
- Comments
- Исправление ошибки JPA “java.lang.Строка не может быть передана в Ljava.lang.Строка;”
- 1. введение
- 2. Распространенный случай ошибки в JPA
- 3. Ручная Фиксация Литья
- 4. Исправление сопоставления сущностей JPA
- 5. Заключение
- Читайте ещё по теме:
How to fix java.lang.classcastexception cannot be cast to in Java — cause and solution
As name suggests ClassCastException in Java comes when we try to type cast an object and object is not of the type we are trying to cast into. In fact ClassCastException in Java is one of most common exception in Java along with java.lang.OutOfMemoryError and ClassNotFoundException in Java before Generics was introduced in Java 5 to avoid frequent instances of java.lang.classcastexception cannot be cast to while working with Collection classes like ArrayList and HashMap, which were not type-safe before Java 5. Though we can minimize and avoid java.lang.ClassCastException in Java by using Generics and writing type-safe parameterized classes and method, its good to know real cause of ClassCastException and How to solve it.
In this Java tutorial we will see Why java.lang.ClassCastException comes and how to resolve ClassCastException in Java. We will also see how to minimize or avoid ClassCastException in Java by using Generics, as prevention is always better than cure.
Cause of java.lang.ClassCastException in Java
In order to understand cause of ClassCastException , you need to be familiar with concept of type casting in Java. Since Java is an object oriented programming language and supports features like Inheritance and Polymorphism, a reference variable of type parent class can represent object of child class. This leads to ClassCastException if object is not of type on which you are casting it. It can be best explained with an example. Let’s see a sample code which will throw ClassCastException in Java:
Exception in thread «main» java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
If you see closely we were trying to cast an String object into an Integer object which is not correct and that’s why Java throws java.lang.classcastexception cannot be cast to error . Problems can become more difficult if all class are closely related.
Since due to polymorphism in Java an Object instance can hold any type of Object but you can only cast between same type. what makes this problem worse is that it only comes during runtime, ClassCastException doesn’t come at compile time which makes it hard to detect specially in large enterprise Java application or high frequency electronic trading system where input comes from upstream and in production various kinds of input are available.
This was frequent problem with Java Collection classes like LinkedList and HashSet in Java which holds Object type but with introduction of Generics in Java 5 solved this problem by checking type-safety during compile time. Which means you can not store Integers on LinkedList of String, from Java 5 it will result in compile time error.
Common source of java.lang.ClassCastException
1. Java Collection classes like HashMap , ArrayList , Vector or Hashtable which is not using Generics.
2. Methods which were written to take advantage of polymorphic behavior and coded on interfaces prior to Java 5 and doesn’t used parameter to provide type-safety. look for all places where you have used cast operator in Java and verify that whether that code is type-safe or not.
Here are some of the most frequently occurred ClassCastException in Java:
java.lang.classcastexception java.lang.string cannot be cast to java.lang.integer
This will come when you try to cast String object to Integer i.e.
Integer number = (Integer) stringObject;
java.lang.classcastexception java.lang.string cannot be cast to java.util.date :
This error will come when you cast String to Date in Java, since both are not related to each other, it will not possible to typecast them.
java.lang.classcastexception java.util.arraylist cannot be cast to java.lang.string
I have seen this happening a lot in beginners code based on Java Collection framework, Since ArrayList and String are not related to each other, following casting will throw this error :
String str = (String) arrayListObject;
But if you definitely wants to convert ArrayList to String, than check this post about converting collection to String in Java.
Here are couple of more examples, which is self explanatory.
java.lang.classcastexception java.util.arraylist cannot be cast to java.util.map
java.lang.classcastexception ljava.lang.object cannot be cast to ljava.lang.comparable
java.lang.classcastexception ljava.lang.object cannot be cast to ljava.lang.integer
java.lang.classcastexception ljava.lang.object cannot be cast to java.util.list
java.util.arraylist cannot be cast to java.lang.comparable
How to fix java.lang.ClassCastException in Java
Solving ClassCastException can be very easy once you understand polymorphism in Java and difference between compile time and runtime things. ClassCastException are simple like NullPointerException just look the stack-trace and go to the line number. Many of advanced Java IDE like Eclipse and Netbeans will give you hyperlink to navigate till culprit line number in Java file.
Now you know where exactly ClassCastException is coming and stack trace also told which object it was trying to cast, Now you have to find, how that type of object comes and this could take some time based upon complexity of your java application. You can also prevent ClassCastException in Java by using Generics.
Generics are designed to write type-safe code and provides compile-time checks which tends to violate type-safety. By using Generics in Collection classes and other places you can safely minimize java.lang.ClassCastException in Java.
That’s all on What is ClassCastException in Java and how to solve Exception in thread «main» java.lang.ClassCastException. I highly recommend to use Generics while using any Collection classes or class which acts as container e.g. ThreadLocal in Java. Also write your own classes and method to take advantage of Generics to provide type-safety as shown in this example of How to write parameterized class. It’s also a good idea to refresh your knowledge on type-casting in Java.
Hibernate HQL casting: java.lang.String cannot be cast to java.lang.Enum
If the field is defined as an enum, you must pass an enum as parameter:
query.setParameter(1, TypeEnum.X);
And let Hibernate use the mapping to transform the parameter into a String (if @Enumerated(EnumType.STRING) is uses) or into an int (if @Enumerated(EnumType.ORDINAL) is used).
Solution 2
using following annotation
@Enumerated (value = EnumType.STRING)
Query q = session.createQuery(from Comment c where c.rating = :rating); q.setParameter(rating, Rating.LOW, Hibernate.custom(RatingUserType.class));
Javi Pedrera
Software Developer. I have worked with: DataBase: SQL, PL/SQL, MySQL BackEnd: Java, JPA, EJB3, Hibernate MVC: JSF, SpringMVC FrontEnd: J2EE, HTML5, CSS, JSP, Facelets, EL, HTML5, CSS, Richfaces, JavaScript, Jquery, AJAX, Swing Testing: Junit, EasyMock Mobile Devices: Android Others: DynamicReports
Comments
java.lang.String cannot be cast to java.lang.Enum
. query = em.createQuery("SELECT object from Entity object where object.column = ?"); query.setParameter(1, "X"); return query.getResultList();
Where in DB the type is a Varchar2(x) with a check constraint and the variable in the entity is defined with Enum using the tag @Enumerated(EnumType.STRING):
Исправление ошибки JPA “java.lang.Строка не может быть передана в Ljava.lang.Строка;”
Узнайте, как исправить распространенную ошибку приведения в запросах JPA.
1. введение
Конечно, мы никогда бы не предположили, что мы можем привести String к массиву String в Java:
java.lang.String cannot be cast to [Ljava.lang.String;
Но, оказывается, это распространенная ошибка JPA.
В этом кратком уроке мы покажем, как это происходит и как это решить.
2. Распространенный случай ошибки в JPA
В JPA нередко возникает эта ошибка , когда мы работаем с собственными запросами и используем метод createNativeQuery в EntityManager .
Его Javadoc фактически предупреждает нас , что этот метод вернет список Object [] или просто Object , если запрос возвращает только один столбец.
Давайте рассмотрим пример. Во-первых, давайте создадим исполнителя запросов, который мы хотим повторно использовать для выполнения всех наших запросов:
public class QueryExecutor < public static ListexecuteNativeQueryNoCastCheck(String statement, EntityManager em) < Query query = em.createNativeQuery(statement); return query.getResultList(); >>
Как было показано выше, мы используем метод createNativeQuery() и всегда ожидаем результирующий набор, содержащий массив String .
После этого давайте создадим простую сущность для использования в наших примерах:
@Entity public class Message < @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String text; // getters and setters >
И, наконец, давайте создадим тестовый класс, который вставляет Сообщение перед запуском тестов:
public class SpringCastUnitTest < private static EntityManager em; private static EntityManagerFactory emFactory; @BeforeClass public static void setup() < emFactory = Persistence.createEntityManagerFactory("jpa-h2"); em = emFactory.createEntityManager(); // insert an object into the db Message message = new Message(); message.setText("text"); EntityTransaction tr = em.getTransaction(); tr.begin(); em.persist(message); tr.commit(); >>
Теперь мы можем использовать наш Исполнитель запросов для выполнения запроса, который извлекает текстовое поле нашей сущности:
@Test(expected = ClassCastException.class) public void givenExecutorNoCastCheck_whenQueryReturnsOneColumn_thenClassCastThrown() < Listresults = QueryExecutor.executeNativeQueryNoCastCheck("select text from message", em); // fails for (String[] row : results) < // do nothing >>
Как мы видим, поскольку в запросе есть только один столбец, JPA фактически вернет список строк, а не список строковых массивов. Мы получаем ClassCastException , потому что запрос возвращает один столбец, и мы ожидали массив.
3. Ручная Фиксация Литья
Самый простой способ исправить эту ошибку-проверить тип объектов результирующего набора , чтобы избежать исключения ClassCastException. Давайте реализуем метод для этого в нашем Исполнителе запросов :
public static ListexecuteNativeQueryWithCastCheck(String statement, EntityManager em) < Query query = em.createNativeQuery(statement); List results = query.getResultList(); if (results.isEmpty()) < return new ArrayList<>(); > if (results.get(0) instanceof String) < return ((List ) results) .stream() .map(s -> new String[] < s >) .collect(Collectors.toList()); > else < return (List ) results; > >
Затем мы можем использовать этот метод для выполнения нашего запроса без получения исключения:
@Test public void givenExecutorWithCastCheck_whenQueryReturnsOneColumn_thenNoClassCastThrown() < Listresults = QueryExecutor.executeNativeQueryWithCastCheck("select text from message", em); assertEquals("text", results.get(0)[0]); >
Это не идеальное решение, так как мы должны преобразовать результат в массив, если запрос возвращает только один столбец.
4. Исправление сопоставления сущностей JPA
Другой способ исправить эту ошибку-сопоставить результирующий набор с сущностью. Таким образом, мы можем заранее решить, как сопоставить результаты наших запросов и избежать ненужных отливок.
Давайте добавим еще один метод к нашему исполнителю для поддержки использования пользовательских сопоставлений сущностей:
public staticList executeNativeQueryGeneric(String statement, String mapping, EntityManager em)
После этого давайте создадим пользовательское SqlResultSetMapping для сопоставления результирующего набора нашего предыдущего запроса с Сообщением сущностью:
@SqlResultSetMapping( name="textQueryMapping", classes= < @ConstructorResult( targetClass=Message.class, columns=< @ColumnResult(name="text") >) > ) @Entity public class Message < // . >
В этом случае мы также должны добавить конструктор, соответствующий нашему недавно созданному SqlResultSetMapping :
public class Message < // . fields and default constructor public Message(String text) < this.text = text; >// . getters and setters >
Наконец, мы можем использовать наш новый метод исполнителя для выполнения тестового запроса и получения списка Сообщений :
@Test public void givenExecutorGeneric_whenQueryReturnsOneColumn_thenNoClassCastThrown() < Listresults = QueryExecutor.executeNativeQueryGeneric( "select text from message", "textQueryMapping", em); assertEquals("text", results.get(0).getText()); >
Это решение намного чище, так как мы делегируем отображение результирующего набора в JPA.
5. Заключение
В этой статье мы показали, что собственные запросы являются общим местом для получения этого ClassCastException . Мы также рассмотрели возможность выполнения проверки типа самостоятельно, а также ее решения путем сопоставления результатов запроса с транспортным объектом.
Как всегда, полный исходный код примеров доступен на GitHub .