How to avoid having to use @SuppressWarnings(“unchecked”)?

北慕城南 提交于 2019-12-22 17:55:06

问题


I have a Cache object for persisting objects to disk, and the way I've implemented this causes me to have to use @SupressWarnings . I'm not a Java expert, but this seems like a code smell, and I'm wondering if there's a 'better' way to do what I'm doing here (for instance, somehow storing a Type when I write the cache, and reading this value to be able to instantiate a specific type?).

My Cache object looks like this (not-relevant code removed for brevity):

/**
 * Write object o to cache file
 * 
 * @param cacheName
 * @param o
 *            Serializable object to write to cache
 */
public static void put(String cacheName, Serializable o) throws IOException {
    FileOutputStream fos = new FileOutputStream(getHashedFileName(cacheName));
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(o);
    fos.close();
}

/**
 * Get an object from the cache. Caller should use exists() before calling
 * here to make sure the cache item exists otherwise Exception will be
 * thrown
 * 
 * @param cacheName
 * @return Object from cache
 */
public static Object get(String cacheName) throws CacheNotFoundException,
        IOException, ClassNotFoundException {
    FileInputStream fis = new FileInputStream(getHashedFileName(cacheName));
    ObjectInputStream ois = new ObjectInputStream(fis);
    Object o = ois.readObject();
    return o;
}

Because get() can return any type of object, I now have to cast it back to the original type when I read from the cache. I'm wondering if I can avoid generating the warning in the first place:

class somethingDoingSomeWork {

    /**
     * Save all work done to the cache.
     * @throws IOException
     */
    public void saveToCache() throws IOException {
        Cache.put(getCacheKey(), (MyObject<String>) summary);
    }

    /**
     * Repopulate from cache
     */
    @SuppressWarnings("unchecked")
    public boolean loadFromCache() throws IOException, CacheNotFoundException,
            ClassNotFoundException {
        // Code removed, checking for existence of cache, etc.

        // Cast required here, and this row generates unchecked warning
        summary = (MyObject<String>) Cache.get(getCacheKey());
        return true;
    }
}

Edit: For people suggesting moving @SuppressWarnings closer to the code, annotations can only be used on lines that are declarations, so this won't help me

Also using generics helps, but it appears to move the problem into the Cache.get() method. The best solution appears to be this: http://www.velocityreviews.com/forums/t499693-how-do-you-prevent-unchecked-cast-warning-when-reading-from-objectinputstream.html


回答1:


and I'm wondering if there's a 'better' way to do what I'm doing here (for instance, somehow storing a Type when I write the cache, and reading this value to be able to instantiate a specific type?)

Use generics here. If you have

public <String, P extends Serializable> R get( String key);
public <String, P extends Serializable> void put( String key, R value);

I am not pointing to already existing Cache implementations. Like Guava, those support cache anyways, but I blieve you want to improve this code.

At the last resort, One big thing is to always keep @SupressWarnings as close as possible to the code causing it.




回答2:


Assuming that both key and value are Serializable you could use these signatures

public <R extends Serializable, P extends Serializable> R get( P key);
public <R extends Serializable, P extends Serializable> void put( P key, R value);



回答3:


Wherever you have like this

// Cast required here, and this row generates unchecked warning
summary = (MyObject) Cache.get(getCacheKey());

It will generates unchecked warning, to avoid this better option to make CollectionHelper class and generates unchecked warning in your CollectionHelper class. And use the CollectionHelper class to return the objects from that class.

For example,

public class CollectionsHelper {
    /**
     * 
     * @param list
     *            of List type
     * @return list - List of MyObject type
     */
    @SuppressWarnings("unchecked")
    public static List<MyObject> getMyObjects(List list) {
        return (List<MyObject>) list;
    }
}

and use it in this way

List<MyObject> objList = CollectionsHelper.getMyObjects(Cache.get(getCacheKey());

You don't need to add @SupressWarnings in your service or implementation class.



来源:https://stackoverflow.com/questions/8971954/how-to-avoid-having-to-use-suppresswarningsunchecked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!