Matthew Brzezinski
Matthew Brzezinski

Reputation: 1794

Casting error when converting double to long

I've run into a strange problem that I'm not understanding. I am working on a Java program that uses the Steam API to get Dota 2 statistics.

for (int i = 0; i < MAX_REQUESTS; i++) {
    competitiveMatches.addAll(getByStartTime(startTime));
    System.out.println("Time: " + competitiveMatches.get(competitiveMatches.size() - 1).getStartTime());
    startTime = competitiveMatches.get(competitiveMatches.size() - 1).getStartTime();
}

I am getting an error on the System.out.println(...) line saying:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long

which to me is not making any sense, I am requesting the last match in my List, and accessing its start_time variable which is the method below. It works by looking through the JSON Map and getting the value at the position.

@Override
public long getStartTime() {
    return (Long) jsonMap.get(KEY_START_TIME);
}

The full stack trace:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long
at de.inkvine.dota2stats.domain.impl.MatchOverviewImpl.getStartTime(MatchOverviewImpl.java:48)
at Silicon.main(Silicon.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Where

An example of a request, the match_id, match_seq_num, and start_time are all stored as doubles e.g. 1.929962146E9:

{  
    "match_id":1929981128,
    "match_seq_num":1705354677,
    "start_time":1447289804,
    "lobby_type":8,
    "radiant_team_id":0,
    "dire_team_id":0,
    "players":[  
        {  
            "account_id":82228820,
            "player_slot":0,
            "hero_id":19
        },
        {  
            "account_id":4294967295,
            "player_slot":128,
            "hero_id":14
        }
    ]
}

Upvotes: 1

Views: 1256

Answers (2)

Kostas Kryptos
Kostas Kryptos

Reputation: 4111

Double, Long, Float, Integer, Long, Short are subclasses of Number, they are not primitives. You cannot cast between them!

Java uses autoboxing only between the primitive types and their corresponding object wrapper classes, but unfortunately it doesn't between Objects and primitives of different Number types eg long to Integer. To help you on casting between different Number types, each Number object is equipped with byteValue(),doubleValue(),floatValue(),intValue(),longValue(),shortValue() methods. So, you can actually call:

jsonMap.get(KEY_START_TIME).longValue();

or you could even use double-casting, taking advantage of autoboxing

(long)(double)jsonMap.get(KEY_START_TIME);

Upvotes: 1

Whymarrh
Whymarrh

Reputation: 13575

You are trying to convert a Double to a long via casting, which is not possible. You can convert the Double to its long counterpart by calling longValue:

@Override
public long getStartTime() {
    return jsonMap.get(KEY_START_TIME).longValue();
}

This is because in JSON, like JavaScript, all numbers are floating point numbers (well, the spec doesn't make any distinction), so it is likely that the JSON library you are using returns you Double objects regardless of whether or not the number has a fractional part.

Upvotes: 1

Related Questions