Как избежать необходимости использовать @SuppressWarnings («не проверено»)? - PullRequest
2 голосов
/ 23 января 2012

У меня есть объект Cache для сохранения объектов на диске, и способ, которым я это реализовал, заставляет меня использовать @SupressWarnings. Я не эксперт по Java, но это похоже на запах кода, и мне интересно, есть ли «лучший» способ сделать то, что я делаю здесь (например, как-то хранить Type, когда я пишу кеш, и чтение этого значения, чтобы иметь возможность создавать конкретный тип?).

Мой объект Cache выглядит так (нерелевантный код удален для краткости):

/**
 * 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;
}

Поскольку get () может возвращать любой тип объекта, теперь мне нужно привести его обратно к исходному типу, когда я читаю из кэша. Мне интересно, смогу ли я вообще избежать предупреждения:

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;
    }
}

Редактировать: Для людей, предлагающих приблизить @SuppressWarnings ближе к коду, аннотации могут использоваться только в строках, которые являются объявлениями, поэтому это не поможет мне

Также помогает использование шаблонов, но, похоже, проблема переносится в метод Cache.get(). Лучшее решение выглядит так: http://www.velocityreviews.com/forums/t499693-how-do-you-prevent-unchecked-cast-warning-when-reading-from-objectinputstream.html

Ответы [ 3 ]

2 голосов
/ 23 января 2012

Если предположить, что ключ и значение Serializable, вы можете использовать эти подписи

public <R extends Serializable, P extends Serializable> R get( P key);
public <R extends Serializable, P extends Serializable> void put( P key, R value);
1 голос
/ 23 января 2012

и мне интересно, есть ли «лучший» способ сделать то, что я делаю здесь (например, каким-то образом сохранить тип, когда я пишу кэш, и прочитать это значение, чтобы иметь возможность создавать конкретный тип? )

Используйте дженерики здесь. Если у вас есть

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

Я не указываю на уже существующие реализации Cache. Как и Guava, они все равно поддерживают кеш, но я рад, что вы хотите улучшить этот код.

В крайнем случае, одна важная вещь - всегда держать @SupressWarnings как можно ближе к вызывающему его коду.

0 голосов
/ 23 января 2012

Где бы вы ни были, как это

// Здесь требуется приведение, и эта строка генерирует непроверенное предупреждение
summary = (MyObject) Cache.get (getCacheKey ());

Он будет генерировать непроверенное предупреждение, чтобы избежать этой лучшей опции для создания класса CollectionHelper, и генерирует непроверенное предупреждение в вашем классе CollectionHelper. И используйте класс CollectionHelper для возврата объектов из этого класса.

Например,

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;
    }
}

и используйте его таким образом

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

Вам не нужно добавлять @SupressWarnings в ваш сервис или класс реализации.

...