Reputation: 670
Here's another bug that I just can't figure out.
I've got this class ExtendedLocation extends Location
that
throws ClassCastException
when instantiated by
currentGpsLocation = new ExtendedLocation((ExtendedLocation) location);
Looking at the stack trace tells me absolutely nothing about a possible solution. Maybe someone smarter than me, can chime in.
I'm pretty new at this java/android stuff, so this might be a simple problem to some, just not for me.
The Exception
: java.lang.ClassCastException: android.location.Location
: at ru.alperez.gpsdub.GpsActivity$1.onLocationChanged(GpsActivity.java:485)
: at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:227)
: at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:160)
: at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:176)
: at android.os.Handler.dispatchMessage(Handler.java:99)
: at android.os.Looper.loop(Looper.java:130)
: at android.app.ActivityThread.main(ActivityThread.java:3687)
: at java.lang.reflect.Method.invokeNative(Native Method)
: at java.lang.reflect.Method.invoke(Method.java:507)
: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
: at dalvik.system.NativeStart.main(Native Method)
ExtendedLocation.class
package ru.alperez.model;
import org.json.JSONException;
import org.json.JSONObject;
import android.location.Location;
public class ExtendedLocation extends Location{
public ExtendedLocation(ExtendedLocation l) {
super(l);
}
public ExtendedLocation(String provider) {
super(provider);
}
public JSONObject toJSON() throws JSONException {
JSONObject ret = new JSONObject();
ret.put("accuracy", this.getAccuracy());
ret.put("altitude", this.getAltitude());
ret.put("bearing", this.getBearing());
ret.put("lat", this.getLatitude());
ret.put("lon", this.getLongitude());
ret.put("provider", this.getProvider());
ret.put("speed", this.getSpeed());
ret.put("time", this.getTime());
return ret;
}
public static ExtendedLocation fromJSON(JSONObject jLocation) {
ExtendedLocation ret = null;
try {
ret = new ExtendedLocation(jLocation.optString("provider"));
ret.setAccuracy((float) jLocation.optDouble("accuracy"));
ret.setAltitude(jLocation.optDouble("altitude"));
ret.setBearing((float) jLocation.optDouble("bearing"));
ret.setLatitude(jLocation.optDouble("lat"));
ret.setLongitude(jLocation.optDouble("lon"));
ret.setSpeed((float) jLocation.optDouble("speed"));
ret.setTime(jLocation.optLong("time"));
} catch (Exception e) {
ret = null;
}
return ret;
}
}
The offending code
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "LocationListener::onLocationChanged: "+location);
try
{
currentGpsLocation = new ExtendedLocation((ExtendedLocation) location);
Log.d(TAG, "LocationListener::onLocationChanged:currentGpsLocation "+currentGpsLocation);
}
catch (ClassCastException e)
{
Log.d(TAG,"ExtendedLocation failed.",e);
return;
}
if (!USE_NMEA) {
populateCurrentGpsData(currentGpsLocation, lastFixState, referenceGpsPoint);
}
}
Upvotes: 1
Views: 855
Reputation: 6640
You are trying to cast a Location
to an ExtendedLocation
:
currentGpsLocation = new ExtendedLocation((ExtendedLocation) location);
^^^^^^^^^^^ here ^^^^^^^^^^
This is not allowed. An ExtendedLocation
is a Location
. This is not true for the other way around: A Location
is not an ExtendedLocation
. Thus, a Location
can not be casted to an ExtendedLocation
.
However, you don't need this. You have to change two spots:
Change the above line to
currentGpsLocation = new ExtendedLocation(location);
and change the constructor of the class ExtendedLocation
to take a Location
instead of an ExtendedLocation
:
public ExtendedLocation(Location l) {
super(l);
}
Upvotes: 0
Reputation: 8478
Base classes shouldn't know anything about classes derived from them, otherwise the problems highlighted above will arise. Downcasting is a 'code smell', and downcasting in the base class to a derived class is particularly 'smelly'. Such designs can lead to difficult to resolve circular dependencies too.
If you want a base class to make use of derived class implementations use the Template method pattern i.e add a virtual or abstract method in your base class and override and implement it in the derived class. You can then safely call this from the base class.
Follow the link below for methods to cast:
Java; casting base class to derived class
Upvotes: 0
Reputation: 685
Your ExtendedLocation should take a Location class object as parameter in consutructor. You also can't cast location object to ExtendLocation.
Upvotes: 0
Reputation: 14710
onLocationChanged
is called by LocationManager
. The object is passed by that manager, it's not an object of your class. Instead of having a constructor like you have there:
public ExtendedLocation(ExtendedLocation l) {
super(l);
}
try to replace it with:
public ExtendedLocation(Location l) {
super(l);
}
and this line from onLocationChanged
currentGpsLocation = new ExtendedLocation((ExtendedLocation) location);
becomes:
currentGpsLocation = new ExtendedLocation(location);
Upvotes: 1
Reputation: 6522
Change parameter of the constructor of ExtendedLocation
to Location
and remove class casting from calling this:
currentGpsLocation = new ExtendedLocation(location);
Upvotes: 0