Сложные непроверенные предупреждения - PullRequest
1 голос
/ 14 февраля 2012

Я пытаюсь очистить некоторый устаревший код и получить несколько unchecked cast предупреждений, от которых я борюсь, чтобы избавиться.

Я извлек код, дающий предупреждения, в скомпилируемую программу ниже.Обратите внимание, что я удалил большую часть кода, чтобы уменьшить его, чтобы он не имел полного смысла.Он компилируется, но его запуск ничего не даст.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;

public class GenericsTest {

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        List<String> stringEntries = reader.readAll(StringEntry.class);
    }

    public static class Reader {

        public <T> ZipInputStream getInputStream(String fileName) throws ZipException, FileNotFoundException {
            return new ZipInputStream(new FileInputStream(fileName));//_file.getInputStream(_paths.get(fileName));
        }

        public <T, TEntry extends Entry<T>> List<T> readAll(Class<TEntry> type) throws IOException {
            List<T> list = new ArrayList<T>();
            List<TEntry> entries = createEntries(type);
            for (TEntry entry : entries) {
                list.add(read(entry));
            }
            return list;
        }

        public <T> T read(Entry<T> entry) throws IOException {
            ZipInputStream is = null;
            try {
                //is = _archive.getInputStream(entry.getName());
                return entry.read(is);
            } finally {
                if (is != null) {
                    is.close();
                }
            }
        }

        public <TEntry extends Entry> List<TEntry> createEntries(Class<TEntry> type) throws ZipException {
            List<TEntry> entries = new ArrayList<TEntry>();
            List<String> paths = new ArrayList<String>();//getPaths(type);
            for (String path : paths) {
                entries.add(createEntry(type, path));
            }
            return entries;
        }

        public <TEntry extends Entry> TEntry createEntry(Class<TEntry> type, String folder) {
            if (StringEntry.class.equals(type)) {
                return (TEntry) new StringEntry(folder);
            } else if (IntegerEntry.class.equals(type)) {
                return (TEntry) new IntegerEntry(folder);
            }
            throw new IllegalArgumentException("Unknown type: " + type);
        }
    }

    public static abstract class Entry<T> extends ZipEntry {

        private T _data;

        public Entry(T data, String folder, String name) {
            super(folder + "/" + name);
            _data = data;
        }

        protected abstract T read(InputStream is) throws IOException;
    };

    public static class StringEntry extends Entry<String> {

        public StringEntry(String folder) {
            super("Hallo world!", folder, "StringEntry");
        }

        @Override
        protected String read(InputStream is) throws IOException {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };

    public static class IntegerEntry extends Entry<Integer> {

        public IntegerEntry(String folder) {
            super(42, folder, "IntegerEntry");
        }

        @Override
        protected Integer read(InputStream is) throws IOException {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };
}

При компиляции приведенного выше кода появляются следующие предупреждения

GenericsTest.java:57: warning: [unchecked] unchecked cast 
found: GenericsTest.StringEntry
required: TEntry
                return (TEntry) new StringEntry(folder);
GenericsTest.java:59: warning: [unchecked] unchecked cast 
found: GenericsTest.IntegerEntry
required: TEntry
                return (TEntry) new IntegerEntry(folder);
2 warnings

Изменение

public <TEntry extends Entry> TEntry createEntry...

на

public <TEntry extends Entry<T>> TEntry createEntry...

приводит к ошибке компилятора(cannot find symbol: class T).

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

Ответы [ 3 ]

2 голосов
/ 14 февраля 2012

Вы уже передаете объект Class в метод, просто используйте Class.cast():

public <TEntry extends Entry<?>> TEntry createEntry(Class<TEntry> type, String folder) {
    if (StringEntry.class.equals(type)) {
        return type.cast(new StringEntry(folder));
    } else if (IntegerEntry.class.equals(type)) {
        return type.cast(new IntegerEntry(folder));
    }
    throw new IllegalArgumentException("Unknown type: " + type);
}

Вышеуказанное изменение заставляет ваш код компилироваться без предупреждений для меня.

Кроме того, <T> в подписи getInputStream(), вероятно, не является необходимым.

2 голосов
/ 14 февраля 2012

Если вы хотите использовать более одного общего параметра, вам нужно будет указать его в списке параметров.Можете ли вы попробовать это?

public <T, TEntry extends Entry<T>> TEntry createEntry(...

ОБНОВЛЕНИЕ

У меня было время поиграть с этим и использовать эти классные объекты класса:

    public <T, TEntry extends Entry<T>> List<TEntry> createEntries(Class<TEntry> type) throws ZipException {
        List<TEntry> entries = new ArrayList<TEntry>();
        List<String> paths = new ArrayList<String>();//getPaths(type);
        for (String path : paths) {
            entries.add(createEntry(type, path));
        }
        return entries;
    }

    public <T, TEntry extends Entry<T>> TEntry createEntry(Class<TEntry> type, String folder) {
        if (StringEntry.class.equals(type)) {
            return type.cast(new StringEntry(folder));
        } else if (IntegerEntry.class.equals(type)) {
            return type.cast(new IntegerEntry(folder));
        }
        throw new IllegalArgumentException("Unknown type: " + type);
    }
}
0 голосов
/ 14 февраля 2012

ИМХО для унаследованного кода, чтобы сделать его универсальным, может быть весьма полезным, особенно если у вас большая база кода ... Поскольку, вероятно, этот код был развернут, вы не рассматриваете итеративный подход?

Под итеративным подходом я имею в виду ... Получите все свои предупреждения и устраните их с помощью @SuppressWarning и аннотации TODO, а затем, со временем, каждый раз, когда вам нужно будет внести изменения в код, если вы наткнетесьна TODO, просто измените его ...

Я просто говорю на тот случай, если вы просто переходите на Java 5 и получаете тысячи предупреждений ..

...