Chris
Chris

Reputation: 4370

java.lang.ClassCastException: java.util.HashSet cannot be cast to Custom Class

FATAL EXCEPTION: AsyncTask #2
Process: my.app, PID: 15441
java.lang.ClassCastException: java.util.HashSet cannot be cast to my.app.ChatNotificationHashSet
at my.app.UserHandler.getChatNotificationMessage(UserHandler.java:127)
at my.app.NotificationUtil.getChatTitle(NotificationUtil.java:100)
at my.app.NotificationUtil.showChat(NotificationUtil.java:71)
at my.app.service.GCMListenerService.onMessageReceived(GCMListenerService.java:47)
at com.google.android.gms.gcm.GcmListenerService.zzq(Unknown Source)
at com.google.android.gms.gcm.GcmListenerService.zzp(Unknown Source)
at com.google.android.gms.gcm.GcmListenerService.zzo(Unknown Source)
at com.google.android.gms.gcm.GcmListenerService.zza(Unknown Source)
at com.google.android.gms.gcm.GcmListenerService$1.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

ChatNotificationHashSet

public class ChatNotificationHashSet<E> extends LinkedHashSet<String> {

    @Override
    public String toString() {
        // ...
    }
}

UserHandler (where the exception occurs)

public ChatNotificationHashSet<String> getChatNotificationMessage() {
        return (ChatNotificationHashSet<String>) pref.getStringSet(CHAT_NOTIFICATION_MESSAGE, null); // <- Exception occurs here
    }

    public void setChatNotificationMessage(ChatNotificationHashSet<String> messages) {
        SharedPreferences.Editor editor = pref.edit();
        editor.putStringSet(CHAT_NOTIFICATION_MESSAGE, messages);
        editor.commit();
    }

How can this happen? There shouldn't be any problems when casting null to ChatNotificationHashSet<String>, right? I couldn't think of any other problem.

Upvotes: 2

Views: 18020

Answers (5)

Henning Luther
Henning Luther

Reputation: 2075

pref.getStringSet() returns a HashSet and not your class, even when it can handle your class as HashSet while saving.

Upvotes: 1

Teddy
Teddy

Reputation: 4223

Values are simply copied into an existing HashSet. Your collection is only a source for the copy.

Refer the comments on this answer: https://stackoverflow.com/a/13446387/1364747

Interface used for modifying values in a SharedPreferences object. All changes you make in an editor are batched, and not copied back to the original SharedPreferences until you call commit() or apply() Source: SharedPreferences.Editor

Only after commit changes are copied to the original SharedPreferences.

Upvotes: 1

Chris
Chris

Reputation: 4370

Thank you guys. I've chosen to save the list as an simple JSON String, which works fine.

Upvotes: 0

Vikrant Kashyap
Vikrant Kashyap

Reputation: 6846

Exception came in your program with this line

 return (ChatNotificationHashSet<String>) pref.getStringSet(CHAT_NOTIFICATION_MESSAGE, null); // <- Exception occurs here

because your ChatNotificationHashSet class is a Strict-Type Argument (simply say generics Supported). So Type-Safety is enabled for this class.

Here getStringSet method return the Object of Type java.util.HashSet<String> which is not a type of ChatNotificationHashSet<String>.

So, Converting a HashSet<String> type Object to ChatNotificationHashSet<String> will prone to ClassCastException as You see in your Code

Upvotes: 0

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

Reputation: 18825

The Set that is returned by getStringSet() does not need to be the same as you pass to SharedPreferences.Editor.putStringSet() method. It's generally up to internal implementation. I assume it serializes the data and puts it into some storage and unserializes when retrieving back.

If you need your specific structure, it's probably better to implement some wrapper which would either read all settings in the constructor or retrieve the settings on demand from underlying Set.

Upvotes: 3

Related Questions