1

I ran into a strange case in my application. It's even more strange because it have been runing for few years so far and there wasn't any problem with this but recently we faced the error.

In very simple example my application does something in similar way as code below (but via polymorphism, the result is the same as in example)

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add(listObjectString().get(0));

        Object date = list.get(0);
        System.out.println(date.getClass()); //OK, prints java.util.Date

        Object date2 = list.get(0).getClass(); //ERROR, ClassCastException
        System.out.println(date2);
    }

    public static List<? extends String> listObjectString(){
        LinkedList list = new LinkedList();
        list.add(new Date());
        return list;
    }

At this point first case doesn't generate error, but when I try to do the same in a single line I'm getting ClassCastException (Date cannot be cast to String).

I checked ByteCode and in second case there is additional line with CHECKCAST.

Can anyone explain how it works? I couldn't find precise answer. Whats more when I was testing this error in my application I've tried it on two devices with the same Java version and the same configuration and on one device I was getting error but on the other one everything was working fine.

Thank you in advance for any answers, that will definitely brighten me the view of this case a little.

Reage
  • 83
  • 4
  • This is a great example of why [we should not use raw types in Java](https://stackoverflow.com/q/2770321/7525132). – Izruo May 12 '22 at 08:13
  • 1
    Sorry but the code works as expected and the Exception is in the line : list.add(listObjectString().get(0)); . JDK 11. – Oussama ZAGHDOUD May 12 '22 at 08:19
  • Not really pertinent to your question, but I recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead use `Instant` or another appropriate class from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. May 12 '22 at 08:29
  • Using Date was only for Example, you probably can put there whatever you want and the result would be the same. I've tried it on Java 8 and 11 and got error as mentioned but your situation seems to be quite similar to what I had with my application, I didn't get error but my friend on seconds device with the same Java version did – Reage May 12 '22 at 09:11
  • I know we shouldn't use Raw types, its just an example which produced similar problem. In my application it's cause because of some polymorphism problem but I've just recreated it on simple example. I'm wondering why it can work on one device and does not on the other, and why getClass() invoke CASTCHECK only on second example but the first one goes without error ;/ – Reage May 12 '22 at 09:13
  • Are you upholding that `list.add(listObjectString().get(0));` throws no exception on either of your devices? Asking because it does for @OussamaZAGHDOUD and me, which in turn prevents us from reproducing the problem that you say you are having. – Ole V.V. May 12 '22 at 09:31
  • This example code I've tested on 4 devices on Java 8 and 11 and everywhere I got error as mentioned on example, I didn't get error during add :/ – Reage May 12 '22 at 09:32
  • I've tested it one more time (with restart and invalidate cache in Intellij) and...on Java 11 there is an error during add, on Java 8 error occures as mentioned in example – Reage May 12 '22 at 09:39
  • @Reage really the problem is not with add method , the problem is with listObjectString().get(0) , adding any thing to the LinkedList is okay because you are declaring the instance using : LinkedList list = new LinkedList() , the problem is with get because when getting the element of the LinkedList Java will automatically cast it to String class because the method return type is : List extends String> , that's why we get the Exception there . Logically on JDK 8 &11 the code will not pass this line : list.add(listObjectString().get(0)); without Exception ! – Oussama ZAGHDOUD May 12 '22 at 10:22
  • So can you tell why it doesnt throw Exception on Java 8? – Reage May 12 '22 at 11:26
  • I _suspect_ that the compiler is adding CHECKCAST in the second case because it is assigning the reference to a variable so it needs to assert that the types are compatible. When you are passing it to the PrintStream it just invokes toString() which all classes implement by nature so there is no need to check type. – vsfDawg May 12 '22 at 12:59
  • @vsDawg that sounds quite logically, so we can say that there is also another difference between Java 8 and 11 because of fact that Java 8 allows us to add this object to our list, but Java 11 throws Exception just when we are about to add object? – Reage May 12 '22 at 13:13

0 Answers0